Merge change 8177

* changes:
  Added patch support based on serializer state in the android client
diff --git a/Android.mk b/Android.mk
index 9c5773f..728ae46 100644
--- a/Android.mk
+++ b/Android.mk
@@ -91,6 +91,7 @@
 	core/java/android/bluetooth/IBluetoothA2dp.aidl \
 	core/java/android/bluetooth/IBluetoothDevice.aidl \
 	core/java/android/bluetooth/IBluetoothHeadset.aidl \
+	core/java/android/bluetooth/IBluetoothPbap.aidl \
 	core/java/android/content/IContentService.aidl \
 	core/java/android/content/IIntentReceiver.aidl \
 	core/java/android/content/IIntentSender.aidl \
@@ -354,7 +355,7 @@
 # most current Android platform version included in the SDK package. 
 framework_docs_SDK_VERSION :=  1.5
 # release version for SDK (ie "Release x")
-framework_docs_SDK_REL_ID :=   2
+framework_docs_SDK_REL_ID :=   3
 framework_docs_SDK_CURRENT_DIR := $(framework_docs_SDK_VERSION)_r$(framework_docs_SDK_REL_ID)
 
 framework_docs_LOCAL_DROIDDOC_OPTIONS += \
@@ -444,7 +445,8 @@
 		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
 		$(web_docs_sample_code_flags) \
 		-toroot / \
-		-hdf android.whichdoc online
+		-hdf android.whichdoc online \
+		-hdf template.showLanguageMenu true
 
 LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
 LOCAL_DROIDDOC_CUSTOM_ASSET_DIR:=assets-sdk
diff --git a/api/current.xml b/api/current.xml
index 9f79118..e76686f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -122,6 +122,28 @@
  visibility="public"
 >
 </field>
+<field name="ACCOUNT_MANAGER_SERVICE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.ACCOUNT_MANAGER_SERVICE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AUTHENTICATE_ACCOUNTS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.AUTHENTICATE_ACCOUNTS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="BATTERY_STATS"
  type="java.lang.String"
  transient="false"
@@ -573,6 +595,17 @@
  visibility="public"
 >
 </field>
+<field name="MANAGE_ACCOUNTS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.MANAGE_ACCOUNTS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MANAGE_APP_TOKENS"
  type="java.lang.String"
  transient="false"
@@ -1079,6 +1112,17 @@
  visibility="public"
 >
 </field>
+<field name="USE_CREDENTIALS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.USE_CREDENTIALS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="VIBRATE"
  type="java.lang.String"
  transient="false"
@@ -2297,6 +2341,17 @@
  visibility="public"
 >
 </field>
+<field name="anyDensity"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843372"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="apiKey"
  type="int"
  transient="false"
@@ -3155,17 +3210,6 @@
  visibility="public"
 >
 </field>
-<field name="density"
- type="int"
- transient="false"
- volatile="false"
- value="16843372"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="dependency"
  type="int"
  transient="false"
@@ -15929,6 +15973,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="context" type="android.content.Context">
+</parameter>
 </constructor>
 <method name="addAccount"
  return="android.os.Bundle"
@@ -16023,6 +16069,19 @@
 <exception name="NetworkErrorException" type="android.accounts.NetworkErrorException">
 </exception>
 </method>
+<method name="getAuthTokenLabel"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="authTokenType" type="java.lang.String">
+</parameter>
+</method>
 <method name="getIAccountAuthenticator"
  return="android.accounts.IAccountAuthenticator"
  abstract="false"
@@ -17335,6 +17394,17 @@
  visibility="public"
 >
 </field>
+<field name="AUTH_TOKEN_LABEL_KEY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;authTokenLabelKey&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="BOOLEAN_RESULT_KEY"
  type="java.lang.String"
  transient="false"
@@ -17715,6 +17785,23 @@
 <exception name="RemoteException" type="android.os.RemoteException">
 </exception>
 </method>
+<method name="getAuthTokenLabel"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="response" type="android.accounts.IAccountAuthenticatorResponse">
+</parameter>
+<parameter name="authTokenType" type="java.lang.String">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</method>
 <method name="hasFeatures"
  return="void"
  abstract="true"
@@ -39175,6 +39262,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_SUPPORTS_SCREEN_DENSITIES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8192"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_SUPPORTS_SMALL_SCREENS"
  type="int"
  transient="false"
@@ -39330,17 +39428,6 @@
  visibility="public"
 >
 </field>
-<field name="supportsDensities"
- type="int[]"
- transient="false"
- volatile="false"
- value="null"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="targetSdkVersion"
  type="int"
  transient="false"
@@ -41252,17 +41339,6 @@
  visibility="public"
 >
 </field>
-<field name="GET_SUPPORTS_DENSITIES"
- type="int"
- transient="false"
- volatile="false"
- value="32768"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="GET_UNINSTALLED_PACKAGES"
  type="int"
  transient="false"
@@ -52865,8 +52941,8 @@
  visibility="public"
 >
 </method>
-<method name="getDensityScale"
- return="float"
+<method name="getDensity"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
@@ -52975,6 +53051,19 @@
 <parameter name="metrics" type="android.util.DisplayMetrics">
 </parameter>
 </method>
+<method name="getScaledHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetDensity" type="int">
+</parameter>
+</method>
 <method name="getScaledWidth"
  return="int"
  abstract="false"
@@ -53001,6 +53090,19 @@
 <parameter name="metrics" type="android.util.DisplayMetrics">
 </parameter>
 </method>
+<method name="getScaledWidth"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetDensity" type="int">
+</parameter>
+</method>
 <method name="getWidth"
  return="int"
  abstract="false"
@@ -53023,17 +53125,6 @@
  visibility="public"
 >
 </method>
-<method name="isAutoScalingEnabled"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="isMutable"
  return="boolean"
  abstract="false"
@@ -53078,7 +53169,7 @@
  visibility="public"
 >
 </method>
-<method name="setAutoScalingEnabled"
+<method name="setDensity"
  return="void"
  abstract="false"
  native="false"
@@ -53088,20 +53179,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="autoScalingEnabled" type="boolean">
-</parameter>
-</method>
-<method name="setDensityScale"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="densityScale" type="float">
+<parameter name="density" type="int">
 </parameter>
 </method>
 <method name="setPixel"
@@ -53171,11 +53249,11 @@
  visibility="public"
 >
 </field>
-<field name="DENSITY_SCALE_UNKNOWN"
- type="float"
+<field name="DENSITY_NONE"
+ type="int"
  transient="false"
  volatile="false"
- value="-1.0f"
+ value="0"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -53391,7 +53469,7 @@
 <parameter name="id" type="int">
 </parameter>
 </method>
-<method name="decodeStream"
+<method name="decodeResourceStream"
  return="android.graphics.Bitmap"
  abstract="false"
  native="false"
@@ -53550,6 +53628,26 @@
  visibility="public"
 >
 </field>
+<field name="inScreenDensity"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="inTargetDensity"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="inTempStorage"
  type="byte[]"
  transient="false"
@@ -54804,8 +54902,8 @@
  visibility="public"
 >
 </method>
-<method name="getDensityScale"
- return="float"
+<method name="getDensity"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
@@ -55161,7 +55259,7 @@
 <parameter name="bitmap" type="android.graphics.Bitmap">
 </parameter>
 </method>
-<method name="setDensityScale"
+<method name="setDensity"
  return="void"
  abstract="false"
  native="false"
@@ -55171,7 +55269,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="densityScale" type="float">
+<parameter name="density" type="int">
 </parameter>
 </method>
 <method name="setDrawFilter"
@@ -57483,6 +57581,17 @@
 <parameter name="paint" type="android.graphics.Paint">
 </parameter>
 </method>
+<method name="getDensity"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getHeight"
  return="int"
  abstract="false"
@@ -62886,7 +62995,7 @@
  type="android.graphics.drawable.BitmapDrawable"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </constructor>
@@ -62897,6 +63006,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+</constructor>
+<constructor name="BitmapDrawable"
+ type="android.graphics.drawable.BitmapDrawable"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="bitmap" type="android.graphics.Bitmap">
+</parameter>
+</constructor>
+<constructor name="BitmapDrawable"
+ type="android.graphics.drawable.BitmapDrawable"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
 <parameter name="bitmap" type="android.graphics.Bitmap">
 </parameter>
 </constructor>
@@ -63062,6 +63193,45 @@
 <parameter name="gravity" type="int">
 </parameter>
 </method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="canvas" type="android.graphics.Canvas">
+</parameter>
+</method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="metrics" type="android.util.DisplayMetrics">
+</parameter>
+</method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="density" type="int">
+</parameter>
+</method>
 <method name="setTileModeX"
  return="void"
  abstract="false"
@@ -63398,6 +63568,25 @@
 <parameter name="pathName" type="java.lang.String">
 </parameter>
 </method>
+<method name="createFromResourceStream"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="value" type="android.util.TypedValue">
+</parameter>
+<parameter name="is" type="java.io.InputStream">
+</parameter>
+<parameter name="srcName" type="java.lang.String">
+</parameter>
+</method>
 <method name="createFromStream"
  return="android.graphics.drawable.Drawable"
  abstract="false"
@@ -65095,7 +65284,7 @@
  type="android.graphics.drawable.NinePatchDrawable"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="bitmap" type="android.graphics.Bitmap">
@@ -65114,6 +65303,36 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="bitmap" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="chunk" type="byte[]">
+</parameter>
+<parameter name="padding" type="android.graphics.Rect">
+</parameter>
+<parameter name="srcName" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="NinePatchDrawable"
+ type="android.graphics.drawable.NinePatchDrawable"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="patch" type="android.graphics.NinePatch">
+</parameter>
+</constructor>
+<constructor name="NinePatchDrawable"
+ type="android.graphics.drawable.NinePatchDrawable"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
 <parameter name="patch" type="android.graphics.NinePatch">
 </parameter>
 </constructor>
@@ -65178,6 +65397,45 @@
 <parameter name="cf" type="android.graphics.ColorFilter">
 </parameter>
 </method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="canvas" type="android.graphics.Canvas">
+</parameter>
+</method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="metrics" type="android.util.DisplayMetrics">
+</parameter>
+</method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="density" type="int">
+</parameter>
+</method>
 </class>
 <class name="PaintDrawable"
  extends="android.graphics.drawable.ShapeDrawable"
@@ -73197,7 +73455,7 @@
  value="1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -73208,7 +73466,7 @@
  value="0"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -73219,7 +73477,7 @@
  value="2"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -73230,6 +73488,358 @@
  value="3"
  static="true"
  final="true"
+ deprecated="deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_INVALID"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_BACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="524288"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_BACK_PROCESSED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8388608"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_DEFAULT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_FRONT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="262144"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_FRONT_PROCESSED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4194304"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_LEFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="65536"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_LEFT_PROCESSED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1048576"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_MONO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="262144"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_PRESSURE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16777216"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_RIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="131072"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_RIGHT_PROCESSED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2097152"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_STEREO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="196608"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_X_AXIS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33554432"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_Y_AXIS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="67108864"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_IN_Z_AXIS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="134217728"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_5POINT1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="63"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_7POINT1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="255"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_BACK_CENTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="256"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_BACK_LEFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_BACK_RIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_DEFAULT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_FRONT_CENTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_FRONT_LEFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_FRONT_LEFT_OF_CENTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="64"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_FRONT_RIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_FRONT_RIGHT_OF_CENTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="128"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_LOW_FREQUENCY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_MONO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_QUAD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="51"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_STEREO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANNEL_OUT_SURROUND"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="263"
+ static="true"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -73347,6 +73957,19 @@
  visibility="public"
 >
 </method>
+<method name="getParameters"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keys" type="java.lang.String">
+</parameter>
+</method>
 <method name="getRingerMode"
  return="int"
  abstract="false"
@@ -73465,6 +74088,17 @@
  visibility="public"
 >
 </method>
+<method name="isWiredHeadsetOn"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="loadSoundEffects"
  return="void"
  abstract="false"
@@ -73511,7 +74145,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="on" type="boolean">
@@ -73556,6 +74190,19 @@
 <parameter name="mode" type="int">
 </parameter>
 </method>
+<method name="setParameters"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyValuePairs" type="java.lang.String">
+</parameter>
+</method>
 <method name="setRingerMode"
  return="void"
  abstract="false"
@@ -73661,6 +74308,19 @@
 <parameter name="vibrateSetting" type="int">
 </parameter>
 </method>
+<method name="setWiredHeadsetOn"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="on" type="boolean">
+</parameter>
+</method>
 <method name="shouldVibrate"
  return="boolean"
  abstract="false"
@@ -74033,7 +74693,7 @@
  value="-1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -74055,7 +74715,7 @@
  value="16"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -74066,7 +74726,7 @@
  value="4"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -74077,7 +74737,7 @@
  value="1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -74088,7 +74748,7 @@
  value="8"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -74099,7 +74759,7 @@
  value="2"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -74114,6 +74774,17 @@
  visibility="public"
 >
 </field>
+<field name="STREAM_DTMF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="STREAM_MUSIC"
  type="int"
  transient="false"
@@ -137455,6 +138126,16 @@
  visibility="public"
 >
 </field>
+<field name="densityDpi"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="heightPixels"
  type="int"
  transient="false"
@@ -138189,6 +138870,62 @@
 >
 </method>
 </class>
+<class name="Pair"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Pair"
+ type="android.util.Pair"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="first" type="F">
+</parameter>
+<parameter name="second" type="S">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.util.Pair&lt;A, B&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="A">
+</parameter>
+<parameter name="b" type="B">
+</parameter>
+</method>
+<field name="first"
+ type="F"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="second"
+ type="S"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="PrintStreamPrinter"
  extends="java.lang.Object"
  abstract="false"
@@ -141159,6 +141896,17 @@
  visibility="public"
 >
 </field>
+<field name="VIRTUAL_KEY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="InflateException"
  extends="java.lang.RuntimeException"
@@ -141999,6 +142747,17 @@
  visibility="public"
 >
 </method>
+<method name="isCanceled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isModifierKey"
  return="boolean"
  abstract="false"
@@ -142114,6 +142873,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_CANCELED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_EDITOR_ACTION"
  type="int"
  transient="false"
@@ -142158,6 +142928,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_VIRTUAL_HARD_KEY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="64"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_WOKE_HERE"
  type="int"
  transient="false"
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 97b43a4..e7c1fbb 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -33,7 +33,6 @@
 #include "CameraService.h"
 
 #include <cutils/atomic.h>
-#include <cutils/properties.h>
 
 namespace android {
 
@@ -199,13 +198,7 @@
 {
     sp<MediaPlayer> mp = new MediaPlayer();
     if (mp->setDataSource(file) == NO_ERROR) {
-        char value[PROPERTY_VALUE_MAX];
-        property_get("ro.camera.sound.forced", value, "0");
-        if (atoi(value)) {
-            mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
-        } else {
-            mp->setAudioStreamType(AudioSystem::SYSTEM);            
-        }
+        mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
         mp->prepare();
     } else {
         mp.clear();
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 3782136..0b4f25e 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -23,16 +23,19 @@
 import android.app.IInstrumentationWatcher;
 import android.app.Instrumentation;
 import android.content.ComponentName;
+import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.util.AndroidException;
 import android.view.IWindowManager;
 
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
 import java.util.Iterator;
 import java.util.Set;
 
@@ -45,16 +48,29 @@
 
     private boolean mDebugOption = false;
 
+    // These are magic strings understood by the Eclipse plugin.
+    private static final String FATAL_ERROR_CODE = "Error type 1";
+    private static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
+    private static final String NO_CLASS_ERROR_CODE = "Error type 3";
+
     /**
      * Command-line entry point.
      *
      * @param args The command-line arguments
      */
     public static void main(String[] args) {
-        (new Am()).run(args);
+        try {
+            (new Am()).run(args);
+        } catch (IllegalArgumentException e) {
+            showUsage();
+            System.err.println("Error: " + e.getMessage());
+        } catch (Exception e) {
+            System.err.println(e.toString());
+            System.exit(1);
+        }
     }
 
-    private void run(String[] args) {
+    private void run(String[] args) throws Exception {
         if (args.length < 1) {
             showUsage();
             return;
@@ -62,16 +78,14 @@
 
         mAm = ActivityManagerNative.getDefault();
         if (mAm == null) {
-            System.err.println("Error type 2");
-            System.err.println("Error: Unable to connect to activity manager; is the system running?");
-            showUsage();
-            return;
+            System.err.println(NO_SYSTEM_ERROR_CODE);
+            throw new AndroidException("Can't connect to activity manager; is the system running?");
         }
 
         mArgs = args;
-
         String op = args[0];
         mNextArg = 1;
+
         if (op.equals("start")) {
             runStart();
         } else if (op.equals("instrument")) {
@@ -81,13 +95,11 @@
         } else if (op.equals("profile")) {
             runProfile();
         } else {
-            System.err.println("Error: Unknown command: " + op);
-            showUsage();
-            return;
+            throw new IllegalArgumentException("Unknown command: " + op);
         }
     }
 
-    private Intent makeIntent() {
+    private Intent makeIntent() throws URISyntaxException {
         Intent intent = new Intent();
         boolean hasIntentInfo = false;
 
@@ -95,186 +107,146 @@
         Uri data = null;
         String type = null;
 
-        try {
-            String opt;
-            while ((opt=nextOption()) != null) {
-                if (opt.equals("-a")) {
-                    intent.setAction(nextOptionData());
-                    hasIntentInfo = true;
-                } else if (opt.equals("-d")) {
-                    data = Uri.parse(nextOptionData());
-                    hasIntentInfo = true;
-                } else if (opt.equals("-t")) {
-                    type = nextOptionData();
-                    hasIntentInfo = true;
-                } else if (opt.equals("-c")) {
-                    intent.addCategory(nextOptionData());
-                    hasIntentInfo = true;
-                } else if (opt.equals("-e") || opt.equals("--es")) {
-                    String key = nextOptionData();
-                    String value = nextOptionData();
-                    intent.putExtra(key, value);
-                    hasIntentInfo = true;
-                } else if (opt.equals("--ei")) {
-                    String key = nextOptionData();
-                    String value = nextOptionData();
-                    intent.putExtra(key, Integer.valueOf(value));
-                    hasIntentInfo = true;
-                } else if (opt.equals("--ez")) {
-                    String key = nextOptionData();
-                    String value = nextOptionData();
-                    intent.putExtra(key, Boolean.valueOf(value));
-                    hasIntentInfo = true;
-                } else if (opt.equals("-n")) {
-                    String str = nextOptionData();
-                    ComponentName cn = ComponentName.unflattenFromString(str);
-                    if (cn == null) {
-                        System.err.println("Error: Bad component name: " + str);
-                        showUsage();
-                        return null;
-                    }
-                    intent.setComponent(cn);
-                    hasIntentInfo = true;
-                } else if (opt.equals("-f")) {
-                    String str = nextOptionData();
-                    intent.setFlags(Integer.decode(str).intValue());
-                } else if (opt.equals("-D")) {
-                    mDebugOption = true;
-                } else {
-                    System.err.println("Error: Unknown option: " + opt);
-                    showUsage();
-                    return null;
-                }
+        String opt;
+        while ((opt=nextOption()) != null) {
+            if (opt.equals("-a")) {
+                intent.setAction(nextArgRequired());
+                hasIntentInfo = true;
+            } else if (opt.equals("-d")) {
+                data = Uri.parse(nextArgRequired());
+                hasIntentInfo = true;
+            } else if (opt.equals("-t")) {
+                type = nextArgRequired();
+                hasIntentInfo = true;
+            } else if (opt.equals("-c")) {
+                intent.addCategory(nextArgRequired());
+                hasIntentInfo = true;
+            } else if (opt.equals("-e") || opt.equals("--es")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                intent.putExtra(key, value);
+                hasIntentInfo = true;
+            } else if (opt.equals("--ei")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                intent.putExtra(key, Integer.valueOf(value));
+                hasIntentInfo = true;
+            } else if (opt.equals("--ez")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                intent.putExtra(key, Boolean.valueOf(value));
+                hasIntentInfo = true;
+            } else if (opt.equals("-n")) {
+                String str = nextArgRequired();
+                ComponentName cn = ComponentName.unflattenFromString(str);
+                if (cn == null) throw new IllegalArgumentException("Bad component name: " + str);
+                intent.setComponent(cn);
+                hasIntentInfo = true;
+            } else if (opt.equals("-f")) {
+                String str = nextArgRequired();
+                intent.setFlags(Integer.decode(str).intValue());
+            } else if (opt.equals("-D")) {
+                mDebugOption = true;
+            } else {
+                System.err.println("Error: Unknown option: " + opt);
+                showUsage();
+                return null;
             }
-        } catch (RuntimeException ex) {
-            System.err.println("Error: " + ex.toString());
-            showUsage();
-            return null;
         }
         intent.setDataAndType(data, type);
 
         String uri = nextArg();
         if (uri != null) {
-            try {
-                Intent oldIntent = intent;
-                try {
-                    intent = Intent.getIntent(uri);
-                } catch (java.net.URISyntaxException ex) {
-                    System.err.println("Bad URI: " + uri);
-                    showUsage();
-                    return null;
-                }
-                if (oldIntent.getAction() != null) {
-                    intent.setAction(oldIntent.getAction());
-                }
-                if (oldIntent.getData() != null || oldIntent.getType() != null) {
-                    intent.setDataAndType(oldIntent.getData(), oldIntent.getType());
-                }
-                Set cats = oldIntent.getCategories();
-                if (cats != null) {
-                    Iterator it = cats.iterator();
-                    while (it.hasNext()) {
-                        intent.addCategory((String)it.next());
-                    }
-                }
-            } catch (RuntimeException ex) {
-                System.err.println("Error creating from URI: " + ex.toString());
-                showUsage();
-                return null;
+            Intent oldIntent = intent;
+            intent = Intent.getIntent(uri);
+            if (oldIntent.getAction() != null) {
+                intent.setAction(oldIntent.getAction());
             }
-        } else if (!hasIntentInfo) {
-            System.err.println("Error: No intent supplied");
-            showUsage();
-            return null;
+            if (oldIntent.getData() != null || oldIntent.getType() != null) {
+                intent.setDataAndType(oldIntent.getData(), oldIntent.getType());
+            }
+            Set cats = oldIntent.getCategories();
+            if (cats != null) {
+                Iterator it = cats.iterator();
+                while (it.hasNext()) {
+                    intent.addCategory((String)it.next());
+                }
+            }
+            hasIntentInfo = true;
         }
 
+        if (!hasIntentInfo) throw new IllegalArgumentException("No intent supplied");
         return intent;
     }
 
-    private void runStart() {
+    private void runStart() throws Exception {
         Intent intent = makeIntent();
-        
-        if (intent != null) {
-            System.out.println("Starting: " + intent);
-            try {
-                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                // XXX should do something to determine the MIME type.
-                int res = mAm.startActivity(null, intent, intent.getType(),
-                        null, 0, null, null, 0, false, mDebugOption);
-                switch (res) {
-                    case IActivityManager.START_SUCCESS:
-                        break;
-                    case IActivityManager.START_SWITCHES_CANCELED:
-                        System.err.println(
-                                "Warning: Activity not started because the "
-                                + " current activity is being kept for the user.");
-                        break;
-                    case IActivityManager.START_DELIVERED_TO_TOP:
-                        System.err.println(
-                                "Warning: Activity not started, intent has "
-                                + "been delivered to currently running "
-                                + "top-most instance.");
-                        break;
-                    case IActivityManager.START_RETURN_INTENT_TO_CALLER:
-                        System.err.println(
-                                "Warning: Activity not started because intent "
-                                + "should be handled by the caller");
-                        break;
-                    case IActivityManager.START_TASK_TO_FRONT:
-                        System.err.println(
-                                "Warning: Activity not started, its current "
-                                + "task has been brought to the front");
-                        break;
-                    case IActivityManager.START_INTENT_NOT_RESOLVED:
-                        System.err.println(
-                                "Error: Activity not started, unable to "
-                                + "resolve " + intent.toString());
-                        break;
-                    case IActivityManager.START_CLASS_NOT_FOUND:
-                        System.err.println("Error type 3");
-                        System.err.println("Error: Activity class " +
-                                intent.getComponent().toShortString()
-                                + " does not exist.");
-                        break;
-                    case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
-                        System.err.println(
-                                "Error: Activity not started, you requested to "
-                                + "both forward and receive its result");
-                        break;
-                    case IActivityManager.START_PERMISSION_DENIED:
-                        System.err.println(
-                                "Error: Activity not started, you do not "
-                                + "have permission to access it.");
-                        break;
-                    default:
-                        System.err.println(
-                                "Error: Activity not started, unknown error "
-                                + "code " + res);
-                        break;
-                }
-            } catch (RemoteException e) {
-                System.err.println("Error type 1");
+        System.out.println("Starting: " + intent);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        // XXX should do something to determine the MIME type.
+        int res = mAm.startActivity(null, intent, intent.getType(),
+                null, 0, null, null, 0, false, mDebugOption);
+        switch (res) {
+            case IActivityManager.START_SUCCESS:
+                break;
+            case IActivityManager.START_SWITCHES_CANCELED:
+                System.err.println(
+                        "Warning: Activity not started because the "
+                        + " current activity is being kept for the user.");
+                break;
+            case IActivityManager.START_DELIVERED_TO_TOP:
+                System.err.println(
+                        "Warning: Activity not started, intent has "
+                        + "been delivered to currently running "
+                        + "top-most instance.");
+                break;
+            case IActivityManager.START_RETURN_INTENT_TO_CALLER:
+                System.err.println(
+                        "Warning: Activity not started because intent "
+                        + "should be handled by the caller");
+                break;
+            case IActivityManager.START_TASK_TO_FRONT:
+                System.err.println(
+                        "Warning: Activity not started, its current "
+                        + "task has been brought to the front");
+                break;
+            case IActivityManager.START_INTENT_NOT_RESOLVED:
                 System.err.println(
                         "Error: Activity not started, unable to "
-                        + "call on to activity manager service");
-            }
+                        + "resolve " + intent.toString());
+                break;
+            case IActivityManager.START_CLASS_NOT_FOUND:
+                System.err.println(NO_CLASS_ERROR_CODE);
+                System.err.println("Error: Activity class " +
+                        intent.getComponent().toShortString()
+                        + " does not exist.");
+                break;
+            case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
+                System.err.println(
+                        "Error: Activity not started, you requested to "
+                        + "both forward and receive its result");
+                break;
+            case IActivityManager.START_PERMISSION_DENIED:
+                System.err.println(
+                        "Error: Activity not started, you do not "
+                        + "have permission to access it.");
+                break;
+            default:
+                System.err.println(
+                        "Error: Activity not started, unknown error code " + res);
+                break;
         }
     }
 
-    private void sendBroadcast() {
+    private void sendBroadcast() throws Exception {
         Intent intent = makeIntent();
-        
-        if (intent != null) {
-            System.out.println("Broadcasting: " + intent);
-            try {
-                mAm.broadcastIntent(null, intent, null, null, 0, null, null,
-                        null, true, false);
-            } catch (RemoteException e) {
-            }
-        }
+        IntentReceiver receiver = new IntentReceiver();
+        System.out.println("Broadcasting: " + intent);
+        mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, null, true, false);
+        receiver.waitForFinish();
     }
 
-    private void runInstrument() {
+    private void runInstrument() throws Exception {
         String profileFile = null;
         boolean wait = false;
         boolean rawMode = false;
@@ -283,46 +255,30 @@
         String argKey = null, argValue = null;
         IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
 
-        try {
-            String opt;
-            while ((opt=nextOption()) != null) {
-                if (opt.equals("-p")) {
-                    profileFile = nextOptionData();
-                } else if (opt.equals("-w")) {
-                    wait = true;
-                } else if (opt.equals("-r")) {
-                    rawMode = true;
-                } else if (opt.equals("-e")) {
-                    argKey = nextOptionData();
-                    argValue = nextOptionData();
-                    args.putString(argKey, argValue);
-                } else if (opt.equals("--no_window_animation")) {
-                    no_window_animation = true;
-                } else {
-                    System.err.println("Error: Unknown option: " + opt);
-                    showUsage();
-                    return;
-                }
+        String opt;
+        while ((opt=nextOption()) != null) {
+            if (opt.equals("-p")) {
+                profileFile = nextArgRequired();
+            } else if (opt.equals("-w")) {
+                wait = true;
+            } else if (opt.equals("-r")) {
+                rawMode = true;
+            } else if (opt.equals("-e")) {
+                argKey = nextArgRequired();
+                argValue = nextArgRequired();
+                args.putString(argKey, argValue);
+            } else if (opt.equals("--no_window_animation")) {
+                no_window_animation = true;
+            } else {
+                System.err.println("Error: Unknown option: " + opt);
+                showUsage();
+                return;
             }
-        } catch (RuntimeException ex) {
-            System.err.println("Error: " + ex.toString());
-            showUsage();
-            return;
         }
 
-        String cnArg = nextArg();
-        if (cnArg == null) {
-            System.err.println("Error: No instrumentation component supplied");
-            showUsage();
-            return;
-        }
-        
+        String cnArg = nextArgRequired();
         ComponentName cn = ComponentName.unflattenFromString(cnArg);
-        if (cn == null) {
-            System.err.println("Error: Bad component name: " + cnArg);
-            showUsage();
-            return;
-        }
+        if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
 
         InstrumentationWatcher watcher = null;
         if (wait) {
@@ -331,22 +287,13 @@
         }
         float[] oldAnims = null;
         if (no_window_animation) {
-            try {
-                oldAnims = wm.getAnimationScales();
-                wm.setAnimationScale(0, 0.0f);
-                wm.setAnimationScale(1, 0.0f);
-            } catch (RemoteException e) {
-            }
+            oldAnims = wm.getAnimationScales();
+            wm.setAnimationScale(0, 0.0f);
+            wm.setAnimationScale(1, 0.0f);
         }
 
-        try {
-            if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
-                System.out.println("INSTRUMENTATION_FAILED: " +
-                        cn.flattenToString());
-                showUsage();
-                return;
-            }
-        } catch (RemoteException e) {
+        if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
+            throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
         }
 
         if (watcher != null) {
@@ -356,9 +303,57 @@
         }
 
         if (oldAnims != null) {
+            wm.setAnimationScales(oldAnims);
+        }
+    }
+
+    private void runProfile() throws Exception {
+        String profileFile = null;
+        boolean start = false;
+        String process = nextArgRequired();
+        ParcelFileDescriptor fd = null;
+
+        String cmd = nextArgRequired();
+        if ("start".equals(cmd)) {
+            start = true;
+            profileFile = nextArgRequired();
             try {
-                wm.setAnimationScales(oldAnims);
-            } catch (RemoteException e) {
+                fd = ParcelFileDescriptor.open(
+                        new File(profileFile),
+                        ParcelFileDescriptor.MODE_CREATE |
+                        ParcelFileDescriptor.MODE_TRUNCATE |
+                        ParcelFileDescriptor.MODE_READ_WRITE);
+            } catch (FileNotFoundException e) {
+                System.err.println("Error: Unable to open file: " + profileFile);
+                return;
+            }
+        } else if (!"stop".equals(cmd)) {
+            throw new IllegalArgumentException("Profile command " + cmd + " not valid");
+        }
+
+        if (!mAm.profileControl(process, start, profileFile, fd)) {
+            throw new AndroidException("PROFILE FAILED on process " + process);
+        }
+    }
+
+    private class IntentReceiver extends IIntentReceiver.Stub {
+        private boolean mFinished = false;
+
+        public synchronized void performReceive(
+                Intent intent, int rc, String data, Bundle ext, boolean ord) {
+            String line = "Broadcast completed: result=" + rc;
+            if (data != null) line = line + ", data=\"" + data + "\"";
+            if (ext != null) line = line + ", extras: " + ext;
+            System.out.println(line);
+            mFinished = true;
+            notifyAll();
+        }
+
+        public synchronized void waitForFinish() {
+            try {
+                while (!mFinished) wait();
+            } catch (InterruptedException e) {
+                throw new IllegalStateException(e);
             }
         }
     }
@@ -366,7 +361,7 @@
     private class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
         private boolean mFinished = false;
         private boolean mRawMode = false;
-        
+
         /**
          * Set or reset "raw mode".  In "raw mode", all bundles are dumped.  In "pretty mode", 
          * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
@@ -375,7 +370,7 @@
         public void setRawOutput(boolean rawMode) {
             mRawMode = rawMode;
         }
-        
+
         public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
             synchronized (this) {
                 // pretty printer mode?
@@ -431,6 +426,7 @@
                         }
                         wait(1000);
                     } catch (InterruptedException e) {
+                        throw new IllegalStateException(e);
                     }
                 }
             }
@@ -438,62 +434,11 @@
         }
     }
 
-    private void runProfile() {
-        String profileFile = null;
-        boolean start = false;
-
-        String process = nextArg();
-        if (process == null) {
-            System.err.println("Error: No profile process supplied");
-            showUsage();
-            return;
-        }
-        
-        ParcelFileDescriptor fd = null;
-        
-        String cmd = nextArg();
-        if ("start".equals(cmd)) {
-            start = true;
-            profileFile = nextArg();
-            if (profileFile == null) {
-                System.err.println("Error: No profile file path supplied");
-                showUsage();
-                return;
-            }
-            try {
-                fd = ParcelFileDescriptor.open(
-                        new File(profileFile),
-                        ParcelFileDescriptor.MODE_CREATE |
-                        ParcelFileDescriptor.MODE_TRUNCATE |
-                        ParcelFileDescriptor.MODE_READ_WRITE);
-            } catch (FileNotFoundException e) {
-                System.err.println("Error: Unable to open file: " + profileFile);
-                return;
-            }
-        } else if (!"stop".equals(cmd)) {
-            System.err.println("Error: Profile command " + cmd + " not valid");
-            showUsage();
-            return;
-        }
-        
-        try {
-            if (!mAm.profileControl(process, start, profileFile, fd)) {
-                System.err.println("PROFILE FAILED on process " + process);
-                return;
-            }
-        } catch (IllegalArgumentException e) {
-            System.out.println("PROFILE FAILED: " + e.getMessage());
-            return;
-        } catch (IllegalStateException e) {
-            System.out.println("PROFILE FAILED: " + e.getMessage());
-            return;
-        } catch (RemoteException e) {
-            System.out.println("PROFILE FAILED: activity manager gone");
-            return;
-        }
-    }
-
     private String nextOption() {
+        if (mCurArgData != null) {
+            String prev = mArgs[mNextArg - 1];
+            throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
+        }
         if (mNextArg >= mArgs.length) {
             return null;
         }
@@ -518,41 +463,52 @@
         return arg;
     }
 
-    private String nextOptionData() {
+    private String nextArg() {
         if (mCurArgData != null) {
-            return mCurArgData;
-        }
-        if (mNextArg >= mArgs.length) {
+            String arg = mCurArgData;
+            mCurArgData = null;
+            return arg;
+        } else if (mNextArg < mArgs.length) {
+            return mArgs[mNextArg++];
+        } else {
             return null;
         }
-        String data = mArgs[mNextArg];
-        mNextArg++;
-        return data;
     }
 
-    private String nextArg() {
-        if (mNextArg >= mArgs.length) {
-            return null;
+    private String nextArgRequired() {
+        String arg = nextArg();
+        if (arg == null) {
+            String prev = mArgs[mNextArg - 1];
+            throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
         }
-        String arg = mArgs[mNextArg];
-        mNextArg++;
         return arg;
     }
 
-    private void showUsage() {
-        System.err.println("usage: am [start|broadcast|instrument|profile]");
-        System.err.println("       am start [-D] INTENT");
-        System.err.println("       am broadcast INTENT");
-        System.err.println("       am instrument [-r] [-e <ARG_NAME> <ARG_VALUE>] [-p <PROF_FILE>]");
-        System.err.println("                [-w] <COMPONENT> ");
-        System.err.println("       am profile <PROCESS> [start <PROF_FILE>|stop]");
-        System.err.println("");
-        System.err.println("       INTENT is described with:");
-        System.err.println("                [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]");
-        System.err.println("                [-c <CATEGORY> [-c <CATEGORY>] ...]");
-        System.err.println("                [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]");
-        System.err.println("                [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]");
-        System.err.println("                [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]");
-        System.err.println("                [-n <COMPONENT>] [-f <FLAGS>] [<URI>]");
+    private static void showUsage() {
+        System.err.println(
+                "usage: am [subcommand] [options]\n" +
+                "\n" +
+                "    start an Activity: am start [-D] <INTENT>\n" +
+                "        -D: enable debugging\n" +
+                "\n" +
+                "    send a broadcast Intent: am broadcast <INTENT>\n" +
+                "\n" +
+                "    start an Instrumentation: am instrument [flags] <COMPONENT>\n" +
+                "        -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)\n" +
+                "        -e <NAME> <VALUE>: set argument <NAME> to <VALUE>\n" +
+                "        -p <FILE>: write profiling data to <FILE>\n" +
+                "        -w: wait for instrumentation to finish before returning\n" +
+                "\n" +
+                "    start profiling: am profile <PROCESS> start <FILE>\n" +
+                "    stop profiling: am profile <PROCESS> stop\n" +
+                "\n" +
+                "    <INTENT> specifications include these flags:\n" +
+                "        [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
+                "        [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
+                "        [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
+                "        [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
+                "        [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
+                "        [-n <COMPONENT>] [-f <FLAGS>] [<URI>]\n"
+                );
     }
 }
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
index 66edd56..c45b53c 100644
--- a/cmds/keystore/keymgmt.c
+++ b/cmds/keystore/keymgmt.c
@@ -79,14 +79,26 @@
 {
     int size, fd, ret = -1;
     unsigned char enc_blob[MAX_BLOB_LEN];
-
     char tmpfile[KEYFILE_LEN];
+
+    if ((keyfile == NULL) || (strlen(keyfile) >= (KEYFILE_LEN - 4))) {
+        LOGE("keyfile name is too long or null");
+        return -1;
+    }
     strcpy(tmpfile, keyfile);
     strcat(tmpfile, ".tmp");
 
     // prepare the blob
+    if (IV_LEN > USER_KEY_LEN) {
+        LOGE("iv length is too long.");
+        return -1;
+    }
     memcpy(blob->iv, iv, IV_LEN);
     blob->blob_size = get_blob_size(blob);
+    if (blob->blob_size > MAX_BLOB_LEN) {
+        LOGE("blob data size is too large.");
+        return -1;
+    }
     memcpy(enc_blob, blob->blob, blob->blob_size);
     AES_cbc_encrypt((unsigned char *)enc_blob, (unsigned char *)blob->blob,
                     blob->blob_size, enc_key, iv, AES_ENCRYPT);
@@ -133,8 +145,13 @@
     DATA_BLOB blob;
 
     // prepare the blob
+    if (strlen(MASTER_KEY_TAG) >= USER_KEY_LEN) return -1;
     strlcpy(blob.keyname, MASTER_KEY_TAG, USER_KEY_LEN);
     blob.value_size = USER_KEY_LEN;
+    if (USER_KEY_LEN > MAX_KEY_VALUE_LENGTH) {
+        LOGE("master_key length is too long.");
+        return -1;
+    }
     memcpy((void*)blob.value, (const void*)master_key, USER_KEY_LEN);
 
     // generate the encryption key
@@ -150,6 +167,10 @@
 
     get_decrypt_key(upasswd, &key);
     ret = load_n_decrypt(MASTER_KEY_TAG, MASTER_KEY, &key, &blob);
+    if (blob.value_size > USER_KEY_LEN) {
+        LOGE("the blob's value size is too large");
+        return -1;
+    }
     if (!ret) memcpy(master_key, blob.value, blob.value_size);
     return ret;
 }
@@ -224,8 +245,16 @@
     }
     sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
     // flatten the args
+    if (strlen(keyname) >= MAX_KEY_NAME_LENGTH) {
+        LOGE("keyname is too long.");
+        return -1;
+    }
     strcpy(blob.keyname, keyname);
     blob.value_size = size;
+    if (size > MAX_KEY_VALUE_LENGTH) {
+        LOGE("the data size is too large.");
+        return -1;
+    }
     memcpy(blob.value, data, size);
     return encrypt_n_save(&encryptKey, &blob, keyfile);
 }
@@ -246,6 +275,7 @@
     ret = load_n_decrypt(keyname, keyfile, &decryptKey, &blob);
     if (!ret) {
         if ((blob.value_size > MAX_KEY_VALUE_LENGTH)) {
+            LOGE("blob value size is too large.");
             ret = -1;
         } else {
             *size = blob.value_size;
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index e4aa8b5..f3a4713 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -30,6 +30,7 @@
     { AID_MEDIA, "media.audio_flinger" },
     { AID_MEDIA, "media.player" },
     { AID_MEDIA, "media.camera" },
+    { AID_MEDIA, "media.audio_policy" },
     { AID_RADIO, "radio.phone" },
     { AID_RADIO, "radio.sms" },
     { AID_RADIO, "radio.phonesubinfo" },
diff --git a/cmds/system_server/library/system_init.cpp b/cmds/system_server/library/system_init.cpp
index ea78461..1d57fdc 100644
--- a/cmds/system_server/library/system_init.cpp
+++ b/cmds/system_server/library/system_init.cpp
@@ -17,6 +17,7 @@
 #include <SurfaceFlinger.h>
 #include <AudioFlinger.h>
 #include <CameraService.h>
+#include <AudioPolicyService.h>
 #include <MediaPlayerService.h>
 
 #include <android_runtime/AndroidRuntime.h>
@@ -80,6 +81,9 @@
 
         // Start the camera service
         CameraService::instantiate();
+
+        // Start the audio policy service
+        AudioPolicyService::instantiate();
     }
 
     // And now start the Android runtime.  We have to do this bit
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index 474755c..3ce3ca3 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -18,6 +18,11 @@
 
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.os.Binder;
+import android.util.Log;
+import android.content.pm.PackageManager;
+import android.content.Context;
+import android.Manifest;
 
 /**
  * Base class for creating AccountAuthenticators. This implements the IAccountAuthenticator
@@ -25,10 +30,17 @@
  * AccountAuthenticators.
  */
 public abstract class AbstractAccountAuthenticator {
+    private final Context mContext;
+
+    public AbstractAccountAuthenticator(Context context) {
+        mContext = context;
+    }
+
     class Transport extends IAccountAuthenticator.Stub {
         public void addAccount(IAccountAuthenticatorResponse response, String accountType,
                 String authTokenType, String[] requiredFeatures, Bundle options)
                 throws RemoteException {
+            checkBinderPermission();
             final Bundle result;
             try {
                 result = AbstractAccountAuthenticator.this.addAccount(
@@ -49,6 +61,7 @@
 
         public void confirmPassword(IAccountAuthenticatorResponse response,
                 Account account, String password) throws RemoteException {
+            checkBinderPermission();
             boolean result;
             try {
                 result = AbstractAccountAuthenticator.this.confirmPassword(
@@ -69,6 +82,7 @@
 
         public void confirmCredentials(IAccountAuthenticatorResponse response,
                 Account account) throws RemoteException {
+            checkBinderPermission();
             final Bundle result;
             try {
                 result = AbstractAccountAuthenticator.this.confirmCredentials(
@@ -83,9 +97,28 @@
             }
         }
 
+        public void getAuthTokenLabel(IAccountAuthenticatorResponse response,
+                String authTokenType)
+                throws RemoteException {
+            checkBinderPermission();
+            try {
+                Bundle result = new Bundle();
+                result.putString(Constants.AUTH_TOKEN_LABEL_KEY,
+                        AbstractAccountAuthenticator.this.getAuthTokenLabel(authTokenType));
+                response.onResult(result);
+            } catch (IllegalArgumentException e) {
+                response.onError(Constants.ERROR_CODE_BAD_ARGUMENTS,
+                        "unknown authTokenType");
+            } catch (UnsupportedOperationException e) {
+                response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION,
+                        "getAuthTokenTypeLabel not supported");
+            }
+        }
+
         public void getAuthToken(IAccountAuthenticatorResponse response,
                 Account account, String authTokenType, Bundle loginOptions)
                 throws RemoteException {
+            checkBinderPermission();
             try {
                 final Bundle result = AbstractAccountAuthenticator.this.getAuthToken(
                         new AccountAuthenticatorResponse(response), account,
@@ -103,6 +136,7 @@
 
         public void updateCredentials(IAccountAuthenticatorResponse response, Account account,
                 String authTokenType, Bundle loginOptions) throws RemoteException {
+            checkBinderPermission();
             final Bundle result;
             try {
                 result = AbstractAccountAuthenticator.this.updateCredentials(
@@ -120,6 +154,7 @@
 
         public void editProperties(IAccountAuthenticatorResponse response,
                 String accountType) throws RemoteException {
+            checkBinderPermission();
             final Bundle result;
             try {
                 result = AbstractAccountAuthenticator.this.editProperties(
@@ -136,6 +171,7 @@
 
         public void hasFeatures(IAccountAuthenticatorResponse response,
                 Account account, String[] features) throws RemoteException {
+            checkBinderPermission();
             final Bundle result;
             try {
                 result = AbstractAccountAuthenticator.this.hasFeatures(
@@ -154,6 +190,14 @@
         }
     }
 
+    private void checkBinderPermission() {
+        final int uid = Binder.getCallingUid();
+        final String perm = Manifest.permission.ACCOUNT_MANAGER_SERVICE;
+        if (mContext.checkCallingOrSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("caller uid " + uid + " lacks " + perm);
+        }
+    }
+
     Transport mTransport = new Transport();
 
     /**
@@ -189,6 +233,7 @@
     public abstract Bundle getAuthToken(AccountAuthenticatorResponse response,
             Account account, String authTokenType, Bundle loginOptions)
             throws NetworkErrorException;
+    public abstract String getAuthTokenLabel(String authTokenType);
     public abstract Bundle updateCredentials(AccountAuthenticatorResponse response,
             Account account, String authTokenType, Bundle loginOptions);
     public abstract Bundle hasFeatures(AccountAuthenticatorResponse response,
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 5182f2e..502abbb 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -652,6 +652,13 @@
                     // that we see
                     mActivity.startActivity(intent);
                     // leave the Future running to wait for the real response to this request
+                } else if (bundle.getBoolean("retry")) {
+                    try {
+                        doWork();
+                    } catch (RemoteException e) {
+                        // this will only happen if the system process is dead, which means
+                        // we will be dying ourselves
+                    }
                 } else {
                     set(bundle);
                 }
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 4f617c4..0c941be 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -21,6 +21,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.RegisteredServicesCache;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDatabase;
@@ -33,18 +35,25 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.Binder;
+import android.os.SystemProperties;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 import android.app.PendingIntent;
 import android.app.NotificationManager;
 import android.app.Notification;
+import android.Manifest;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashMap;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
 
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.R;
@@ -63,7 +72,7 @@
 
     private static final int TIMEOUT_DELAY_MS = 1000 * 60;
     private static final String DATABASE_NAME = "accounts.db";
-    private static final int DATABASE_VERSION = 2;
+    private static final int DATABASE_VERSION = 3;
 
     private final Context mContext;
 
@@ -92,6 +101,11 @@
     private static final String AUTHTOKENS_TYPE = "type";
     private static final String AUTHTOKENS_AUTHTOKEN = "authtoken";
 
+    private static final String TABLE_GRANTS = "grants";
+    private static final String GRANTS_ACCOUNTS_ID = "accounts_id";
+    private static final String GRANTS_AUTH_TOKEN_TYPE = "auth_token_type";
+    private static final String GRANTS_GRANTEE_UID = "uid";
+
     private static final String TABLE_EXTRAS = "extras";
     private static final String EXTRAS_ID = "_id";
     private static final String EXTRAS_ACCOUNTS_ID = "accounts_id";
@@ -107,8 +121,37 @@
     private static final Intent ACCOUNTS_CHANGED_INTENT =
             new Intent(Constants.LOGIN_ACCOUNTS_CHANGED_ACTION);
 
+    private static final String COUNT_OF_MATCHING_GRANTS = ""
+            + "SELECT COUNT(*) FROM " + TABLE_GRANTS + ", " + TABLE_ACCOUNTS
+            + " WHERE " + GRANTS_ACCOUNTS_ID + "=" + ACCOUNTS_ID
+            + " AND " + GRANTS_GRANTEE_UID + "=?"
+            + " AND " + GRANTS_AUTH_TOKEN_TYPE + "=?"
+            + " AND " + ACCOUNTS_NAME + "=?"
+            + " AND " + ACCOUNTS_TYPE + "=?";
+
     private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>();
-    private static final int NOTIFICATION_ID = 234;
+    private final AtomicInteger mNotificationIds = new AtomicInteger(1);
+
+    private final HashMap<Pair<Pair<Account, String>, Integer>, Integer>
+            mCredentialsPermissionNotificationIds =
+            new HashMap<Pair<Pair<Account, String>, Integer>, Integer>();
+    private final HashMap<Account, Integer> mSigninRequiredNotificationIds =
+            new HashMap<Account, Integer>();
+    private static AtomicReference<AccountManagerService> sThis =
+            new AtomicReference<AccountManagerService>();
+
+    private static final boolean isDebuggableMonkeyBuild =
+            SystemProperties.getBoolean("ro.monkey", false)
+                    && SystemProperties.getBoolean("ro.debuggable", false);
+    /**
+     * This should only be called by system code. One should only call this after the service
+     * has started.
+     * @return a reference to the AccountManagerService instance
+     * @hide
+     */
+    public static AccountManagerService getSingleton() {
+        return sThis.get();
+    }
 
     public class AuthTokenKey {
         public final Account mAccount;
@@ -163,9 +206,12 @@
                 MESSAGE_CONNECTED, MESSAGE_DISCONNECTED);
 
         mSimWatcher = new SimWatcher(mContext);
+        sThis.set(this);
     }
 
     public String getPassword(Account account) {
+        checkAuthenticateAccountsPermission(account);
+
         long identityToken = clearCallingIdentity();
         try {
             SQLiteDatabase db = mOpenHelper.getReadableDatabase();
@@ -186,6 +232,7 @@
     }
 
     public String getUserData(Account account, String key) {
+        checkAuthenticateAccountsPermission(account);
         long identityToken = clearCallingIdentity();
         try {
             SQLiteDatabase db = mOpenHelper.getReadableDatabase();
@@ -207,7 +254,6 @@
                     cursor.close();
                 }
             } finally {
-                db.setTransactionSuccessful();
                 db.endTransaction();
             }
         } finally {
@@ -235,6 +281,7 @@
     }
 
     public Account[] getAccounts() {
+        checkReadAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
             return getAccountsByType(null);
@@ -244,6 +291,7 @@
     }
 
     public Account[] getAccountsByType(String accountType) {
+        checkReadAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
             SQLiteDatabase db = mOpenHelper.getReadableDatabase();
@@ -269,6 +317,8 @@
     }
 
     public boolean addAccount(Account account, String password, Bundle extras) {
+        checkAuthenticateAccountsPermission(account);
+
         // fails if the account already exists
         long identityToken = clearCallingIdentity();
         try {
@@ -318,6 +368,7 @@
     }
 
     public void removeAccount(Account account) {
+        checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
             final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
@@ -330,6 +381,7 @@
     }
 
     public void invalidateAuthToken(String accountType, String authToken) {
+        checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
             SQLiteDatabase db = mOpenHelper.getWritableDatabase();
@@ -404,12 +456,12 @@
             }
             return getAuthToken(db, accountId, authTokenType);
         } finally {
-            db.setTransactionSuccessful();
             db.endTransaction();
         }
     }
 
     public String peekAuthToken(Account account, String authTokenType) {
+        checkAuthenticateAccountsPermission(account);
         long identityToken = clearCallingIdentity();
         try {
             return readAuthTokenFromDatabase(account, authTokenType);
@@ -419,6 +471,7 @@
     }
 
     public void setAuthToken(Account account, String authTokenType, String authToken) {
+        checkAuthenticateAccountsPermission(account);
         long identityToken = clearCallingIdentity();
         try {
             cacheAuthToken(account, authTokenType, authToken);
@@ -428,6 +481,7 @@
     }
 
     public void setPassword(Account account, String password) {
+        checkAuthenticateAccountsPermission(account);
         long identityToken = clearCallingIdentity();
         try {
             ContentValues values = new ContentValues();
@@ -446,6 +500,7 @@
     }
 
     public void clearPassword(Account account) {
+        checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
             setPassword(account, null);
@@ -455,6 +510,7 @@
     }
 
     public void setUserData(Account account, String key, String value) {
+        checkAuthenticateAccountsPermission(account);
         long identityToken = clearCallingIdentity();
         try {
             SQLiteDatabase db = mOpenHelper.getWritableDatabase();
@@ -487,26 +543,39 @@
         }
     }
 
+    private void onResult(IAccountManagerResponse response, Bundle result) {
+        try {
+            response.onResult(result);
+        } catch (RemoteException e) {
+            // if the caller is dead then there is no one to care about remote
+            // exceptions
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, "failure while notifying response", e);
+            }
+        }
+    }
+
     public void getAuthToken(IAccountManagerResponse response, final Account account,
             final String authTokenType, final boolean notifyOnAuthFailure,
             final boolean expectActivityLaunch, final Bundle loginOptions) {
+        checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
+        final int callerUid = Binder.getCallingUid();
+        final boolean permissionGranted = permissionIsGranted(account, authTokenType, callerUid);
+
         long identityToken = clearCallingIdentity();
         try {
-            String authToken = readAuthTokenFromDatabase(account, authTokenType);
-            if (authToken != null) {
-                try {
+            // if the caller has permission, do the peek. otherwise go the more expensive
+            // route of starting a Session
+            if (permissionGranted) {
+                String authToken = readAuthTokenFromDatabase(account, authTokenType);
+                if (authToken != null) {
                     Bundle result = new Bundle();
                     result.putString(Constants.AUTHTOKEN_KEY, authToken);
                     result.putString(Constants.ACCOUNT_NAME_KEY, account.mName);
                     result.putString(Constants.ACCOUNT_TYPE_KEY, account.mType);
-                    response.onResult(result);
-                } catch (RemoteException e) {
-                    // if the caller is dead then there is no one to care about remote exceptions
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "failure while notifying response", e);
-                    }
+                    onResult(response, result);
+                    return;
                 }
-                return;
             }
 
             new Session(response, account.mType, expectActivityLaunch) {
@@ -520,11 +589,27 @@
                 }
 
                 public void run() throws RemoteException {
-                    mAuthenticator.getAuthToken(this, account, authTokenType, loginOptions);
+                    // If the caller doesn't have permission then create and return the
+                    // "grant permission" intent instead of the "getAuthToken" intent.
+                    if (!permissionGranted) {
+                        mAuthenticator.getAuthTokenLabel(this, authTokenType);
+                    } else {
+                        mAuthenticator.getAuthToken(this, account, authTokenType, loginOptions);
+                    }
                 }
 
                 public void onResult(Bundle result) {
                     if (result != null) {
+                        if (result.containsKey(Constants.AUTH_TOKEN_LABEL_KEY)) {
+                            Intent intent = newGrantCredentialsPermissionIntent(account, callerUid,
+                                    new AccountAuthenticatorResponse(this),
+                                    authTokenType,
+                                    result.getString(Constants.AUTH_TOKEN_LABEL_KEY));
+                            Bundle bundle = new Bundle();
+                            bundle.putParcelable(Constants.INTENT_KEY, intent);
+                            onResult(bundle);
+                            return;
+                        }
                         String authToken = result.getString(Constants.AUTHTOKEN_KEY);
                         if (authToken != null) {
                             String name = result.getString(Constants.ACCOUNT_NAME_KEY);
@@ -539,7 +624,8 @@
 
                         Intent intent = result.getParcelable(Constants.INTENT_KEY);
                         if (intent != null && notifyOnAuthFailure) {
-                            doNotification(result.getString(Constants.AUTH_FAILED_MESSAGE_KEY),
+                            doNotification(
+                                    account, result.getString(Constants.AUTH_FAILED_MESSAGE_KEY),
                                     intent);
                         }
                     }
@@ -551,10 +637,92 @@
         }
     }
 
+    private void createNoCredentialsPermissionNotification(Account account, Intent intent) {
+        int uid = intent.getIntExtra(
+                GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, -1);
+        String authTokenType = intent.getStringExtra(
+                GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE);
+        String authTokenLabel = intent.getStringExtra(
+                GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL);
+
+        Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
+                0 /* when */);
+        final CharSequence subtitleFormatString =
+                mContext.getText(R.string.permission_request_notification_subtitle);
+        n.setLatestEventInfo(mContext,
+                mContext.getText(R.string.permission_request_notification_title),
+                String.format(subtitleFormatString.toString(), account.mName),
+                PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
+        ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
+                .notify(getCredentialPermissionNotificationId(account, authTokenType, uid), n);
+    }
+
+    private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
+            AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
+        RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo =
+                mAuthenticatorCache.getServiceInfo(
+                        AuthenticatorDescription.newKey(account.mType));
+        if (serviceInfo == null) {
+            throw new IllegalArgumentException("unknown account type: " + account.mType);
+        }
+
+        final Context authContext;
+        try {
+            authContext = mContext.createPackageContext(
+                serviceInfo.type.packageName, 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new IllegalArgumentException("unknown account type: " + account.mType);
+        }
+
+        Intent intent = new Intent(mContext, GrantCredentialsPermissionActivity.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.addCategory(
+                String.valueOf(getCredentialPermissionNotificationId(account, authTokenType, uid)));
+        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT, account);
+        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL, authTokenLabel);
+        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE, authTokenType);
+        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_RESPONSE, response);
+        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT_TYPE_LABEL,
+                        authContext.getString(serviceInfo.type.labelId));
+        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_PACKAGES,
+                        mContext.getPackageManager().getPackagesForUid(uid));
+        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, uid);
+        return intent;
+    }
+
+    private Integer getCredentialPermissionNotificationId(Account account, String authTokenType,
+            int uid) {
+        Integer id;
+        synchronized(mCredentialsPermissionNotificationIds) {
+            final Pair<Pair<Account, String>, Integer> key =
+                    new Pair<Pair<Account, String>, Integer>(
+                            new Pair<Account, String>(account, authTokenType), uid);
+            id = mCredentialsPermissionNotificationIds.get(key);
+            if (id == null) {
+                id = mNotificationIds.incrementAndGet();
+                mCredentialsPermissionNotificationIds.put(key, id);
+            }
+        }
+        return id;
+    }
+
+    private Integer getSigninRequiredNotificationId(Account account) {
+        Integer id;
+        synchronized(mSigninRequiredNotificationIds) {
+            id = mSigninRequiredNotificationIds.get(account);
+            if (id == null) {
+                id = mNotificationIds.incrementAndGet();
+                mSigninRequiredNotificationIds.put(account, id);
+            }
+        }
+        return id;
+    }
+
 
     public void addAcount(final IAccountManagerResponse response, final String accountType,
             final String authTokenType, final String[] requiredFeatures,
             final boolean expectActivityLaunch, final Bundle options) {
+        checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
             new Session(response, accountType, expectActivityLaunch) {
@@ -579,6 +747,7 @@
 
     public void confirmCredentials(IAccountManagerResponse response,
             final Account account, final boolean expectActivityLaunch) {
+        checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
             new Session(response, account.mType, expectActivityLaunch) {
@@ -597,6 +766,7 @@
 
     public void confirmPassword(IAccountManagerResponse response, final Account account,
             final String password) {
+        checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
             new Session(response, account.mType, false /* expectActivityLaunch */) {
@@ -616,6 +786,7 @@
     public void updateCredentials(IAccountManagerResponse response, final Account account,
             final String authTokenType, final boolean expectActivityLaunch,
             final Bundle loginOptions) {
+        checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
             new Session(response, account.mType, expectActivityLaunch) {
@@ -637,6 +808,7 @@
 
     public void editProperties(IAccountManagerResponse response, final String accountType,
             final boolean expectActivityLaunch) {
+        checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
             new Session(response, accountType, expectActivityLaunch) {
@@ -728,6 +900,7 @@
     }
     public void getAccountsByTypeAndFeatures(IAccountManagerResponse response,
             String type, String[] features) {
+        checkReadAccountsPermission();
         if (type == null) {
             if (response != null) {
                 try {
@@ -929,7 +1102,12 @@
         public void onResult(Bundle result) {
             mNumResults++;
             if (result != null && !TextUtils.isEmpty(result.getString(Constants.AUTHTOKEN_KEY))) {
-                cancelNotification();
+                String accountName = result.getString(Constants.ACCOUNT_NAME_KEY);
+                String accountType = result.getString(Constants.ACCOUNT_TYPE_KEY);
+                if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
+                    Account account = new Account(accountName, accountType);
+                    cancelNotification(getSigninRequiredNotificationId(account));
+                }
             }
             IAccountManagerResponse response;
             if (mExpectActivityLaunch && result != null
@@ -1026,6 +1204,8 @@
                     + AUTHTOKENS_AUTHTOKEN + " TEXT,  "
                     + "UNIQUE (" + AUTHTOKENS_ACCOUNTS_ID + "," + AUTHTOKENS_TYPE + "))");
 
+            createGrantsTable(db);
+
             db.execSQL("CREATE TABLE " + TABLE_EXTRAS + " ( "
                     + EXTRAS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
                     + EXTRAS_ACCOUNTS_ID + " INTEGER, "
@@ -1037,6 +1217,10 @@
                     + META_KEY + " TEXT PRIMARY KEY NOT NULL, "
                     + META_VALUE + " TEXT)");
 
+            createAccountsDeletionTrigger(db);
+        }
+
+        private void createAccountsDeletionTrigger(SQLiteDatabase db) {
             db.execSQL(""
                     + " CREATE TRIGGER " + TABLE_ACCOUNTS + "Delete DELETE ON " + TABLE_ACCOUNTS
                     + " BEGIN"
@@ -1044,22 +1228,34 @@
                     + "     WHERE " + AUTHTOKENS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
                     + "   DELETE FROM " + TABLE_EXTRAS
                     + "     WHERE " + EXTRAS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
+                    + "   DELETE FROM " + TABLE_GRANTS
+                    + "     WHERE " + GRANTS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
                     + " END");
         }
 
+        private void createGrantsTable(SQLiteDatabase db) {
+            db.execSQL("CREATE TABLE " + TABLE_GRANTS + " (  "
+                    + GRANTS_ACCOUNTS_ID + " INTEGER NOT NULL, "
+                    + GRANTS_AUTH_TOKEN_TYPE + " STRING NOT NULL,  "
+                    + GRANTS_GRANTEE_UID + " INTEGER NOT NULL,  "
+                    + "UNIQUE (" + GRANTS_ACCOUNTS_ID + "," + GRANTS_AUTH_TOKEN_TYPE
+                    +   "," + GRANTS_GRANTEE_UID + "))");
+        }
+
         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
             Log.e(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
 
             if (oldVersion == 1) {
-                db.execSQL(""
-                        + " CREATE TRIGGER " + TABLE_ACCOUNTS + "Delete DELETE ON " + TABLE_ACCOUNTS
-                        + " BEGIN"
-                        + "   DELETE FROM " + TABLE_AUTHTOKENS
-                        + "     WHERE " + AUTHTOKENS_ACCOUNTS_ID + " =OLD." + ACCOUNTS_ID + " ;"
-                        + "   DELETE FROM " + TABLE_EXTRAS
-                        + "     WHERE " + EXTRAS_ACCOUNTS_ID + " =OLD." + ACCOUNTS_ID + " ;"
-                        + " END");
+                // no longer need to do anything since the work is done
+                // when upgrading from version 2
+                oldVersion++;
+            }
+
+            if (oldVersion == 2) {
+                createGrantsTable(db);
+                db.execSQL("DROP TRIGGER " + TABLE_ACCOUNTS + "Delete");
+                createAccountsDeletionTrigger(db);
                 oldVersion++;
             }
         }
@@ -1156,31 +1352,171 @@
         mAuthenticatorCache.dump(fd, fout, args);
     }
 
-    private void doNotification(CharSequence message, Intent intent) {
+    private void doNotification(Account account, CharSequence message, Intent intent) {
         long identityToken = clearCallingIdentity();
         try {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.v(TAG, "doNotification: " + message + " intent:" + intent);
             }
 
-            Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
-                    0 /* when */);
-            n.setLatestEventInfo(mContext, mContext.getText(R.string.notification_title), message,
-                PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
-            ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
-                    .notify(NOTIFICATION_ID, n);
+            if (intent.getComponent() != null &&
+                    GrantCredentialsPermissionActivity.class.getName().equals(
+                            intent.getComponent().getClassName())) {
+                createNoCredentialsPermissionNotification(account, intent);
+            } else {
+                Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
+                        0 /* when */);
+                n.setLatestEventInfo(mContext, mContext.getText(R.string.notification_title),
+                        message, PendingIntent.getActivity(
+                        mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
+                ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
+                        .notify(getSigninRequiredNotificationId(account), n);
+            }
         } finally {
             restoreCallingIdentity(identityToken);
         }
     }
 
-    private void cancelNotification() {
+    private void cancelNotification(int id) {
         long identityToken = clearCallingIdentity();
         try {
             ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
-                .cancel(NOTIFICATION_ID);
+                .cancel(id);
         } finally {
             restoreCallingIdentity(identityToken);
         }
     }
+
+    private void checkBinderPermission(String permission) {
+        final int uid = Binder.getCallingUid();
+        if (mContext.checkCallingOrSelfPermission(permission) !=
+                PackageManager.PERMISSION_GRANTED) {
+            String msg = "caller uid " + uid + " lacks " + permission;
+            Log.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "caller uid " + uid + " has " + permission);
+        }
+    }
+
+    private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
+        final boolean fromAuthenticator = hasAuthenticatorUid(account.mType, callerUid);
+        final boolean hasExplicitGrants = hasExplicitlyGrantedPermission(account, authTokenType);
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "checkGrantsOrCallingUidAgainstAuthenticator: caller uid "
+                    + callerUid + ", account " + account
+                    + ": is authenticator? " + fromAuthenticator
+                    + ", has explicit permission? " + hasExplicitGrants);
+        }
+        return fromAuthenticator || hasExplicitGrants;
+    }
+
+    private boolean hasAuthenticatorUid(String accountType, int callingUid) {
+        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
+                mAuthenticatorCache.getAllServices()) {
+            if (serviceInfo.type.type.equals(accountType)) {
+                return serviceInfo.uid == callingUid;
+            }
+        }
+        return false;
+    }
+
+    private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType) {
+        if (Binder.getCallingUid() == android.os.Process.SYSTEM_UID) {
+            return true;
+        }
+        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+        String[] args = {String.valueOf(Binder.getCallingUid()), authTokenType,
+                account.mName, account.mType};
+        final boolean permissionGranted =
+                DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args) != 0;
+        if (!permissionGranted && isDebuggableMonkeyBuild) {
+            // TODO: Skip this check when running automated tests. Replace this
+            // with a more general solution.
+            Log.w(TAG, "no credentials permission for usage of " + account + ", "
+                    + authTokenType + " by uid " + Binder.getCallingUid()
+                    + " but ignoring since this is a monkey build");
+            return true;
+        }
+        return permissionGranted;
+    }
+
+    private void checkCallingUidAgainstAuthenticator(Account account) {
+        final int uid = Binder.getCallingUid();
+        if (!hasAuthenticatorUid(account.mType, uid)) {
+            String msg = "caller uid " + uid + " is different than the authenticator's uid";
+            Log.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "caller uid " + uid + " is the same as the authenticator's uid");
+        }
+    }
+
+    private void checkAuthenticateAccountsPermission(Account account) {
+        checkBinderPermission(Manifest.permission.AUTHENTICATE_ACCOUNTS);
+        checkCallingUidAgainstAuthenticator(account);
+    }
+
+    private void checkReadAccountsPermission() {
+        checkBinderPermission(Manifest.permission.GET_ACCOUNTS);
+    }
+
+    private void checkManageAccountsPermission() {
+        checkBinderPermission(Manifest.permission.MANAGE_ACCOUNTS);
+    }
+
+    /**
+     * Allow callers with the given uid permission to get credentials for account/authTokenType.
+     * <p>
+     * Although this is public it can only be accessed via the AccountManagerService object
+     * which is in the system. This means we don't need to protect it with permissions.
+     * @hide
+     */
+    public void grantAppPermission(Account account, String authTokenType, int uid) {
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        db.beginTransaction();
+        try {
+            long accountId = getAccountId(db, account);
+            if (accountId >= 0) {
+                ContentValues values = new ContentValues();
+                values.put(GRANTS_ACCOUNTS_ID, accountId);
+                values.put(GRANTS_AUTH_TOKEN_TYPE, authTokenType);
+                values.put(GRANTS_GRANTEE_UID, uid);
+                db.insert(TABLE_GRANTS, GRANTS_ACCOUNTS_ID, values);
+                db.setTransactionSuccessful();
+            }
+        } finally {
+            db.endTransaction();
+        }
+        cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid));
+    }
+
+    /**
+     * Don't allow callers with the given uid permission to get credentials for
+     * account/authTokenType.
+     * <p>
+     * Although this is public it can only be accessed via the AccountManagerService object
+     * which is in the system. This means we don't need to protect it with permissions.
+     * @hide
+     */
+    public void revokeAppPermission(Account account, String authTokenType, int uid) {
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        db.beginTransaction();
+        try {
+            long accountId = getAccountId(db, account);
+            if (accountId >= 0) {
+                db.delete(TABLE_GRANTS,
+                        GRANTS_ACCOUNTS_ID + "=? AND " + GRANTS_AUTH_TOKEN_TYPE + "=? AND "
+                                + GRANTS_GRANTEE_UID + "=?",
+                        new String[]{String.valueOf(accountId), authTokenType,
+                                String.valueOf(uid)});
+                db.setTransactionSuccessful();
+            }
+        } finally {
+            db.endTransaction();
+        }
+        cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid));
+    }
 }
diff --git a/core/java/android/accounts/Constants.java b/core/java/android/accounts/Constants.java
index bb7f940..da8173f 100644
--- a/core/java/android/accounts/Constants.java
+++ b/core/java/android/accounts/Constants.java
@@ -40,6 +40,7 @@
     public static final String ACCOUNT_AUTHENTICATOR_RESPONSE_KEY = "accountAuthenticatorResponse";
     public static final String ACCOUNT_MANAGER_RESPONSE_KEY = "accountManagerResponse";
     public static final String AUTH_FAILED_MESSAGE_KEY = "authFailedMessage";
+    public static final String AUTH_TOKEN_LABEL_KEY = "authTokenLabelKey";
 
     public static final String AUTHENTICATOR_INTENT_ACTION =
             "android.accounts.AccountAuthenticator";
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
new file mode 100644
index 0000000..f92d43f
--- /dev/null
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2009 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.accounts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.view.View;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import com.android.internal.R;
+
+/**
+ * @hide
+ */
+public class GrantCredentialsPermissionActivity extends Activity implements View.OnClickListener {
+    public static final String EXTRAS_ACCOUNT = "account";
+    public static final String EXTRAS_AUTH_TOKEN_LABEL = "authTokenLabel";
+    public static final String EXTRAS_AUTH_TOKEN_TYPE = "authTokenType";
+    public static final String EXTRAS_RESPONSE = "response";
+    public static final String EXTRAS_ACCOUNT_TYPE_LABEL = "accountTypeLabel";
+    public static final String EXTRAS_PACKAGES = "application";
+    public static final String EXTRAS_REQUESTING_UID = "uid";
+    private Account mAccount;
+    private String mAuthTokenType;
+    private int mUid;
+    private Bundle mResultBundle = null;
+
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().setContentView(R.layout.grant_credentials_permission);
+        mAccount = getIntent().getExtras().getParcelable(EXTRAS_ACCOUNT);
+        mAuthTokenType = getIntent().getExtras().getString(EXTRAS_AUTH_TOKEN_TYPE);
+        mUid = getIntent().getExtras().getInt(EXTRAS_REQUESTING_UID);
+        final String accountTypeLabel =
+                getIntent().getExtras().getString(EXTRAS_ACCOUNT_TYPE_LABEL);
+        final String[] packages = getIntent().getExtras().getStringArray(EXTRAS_PACKAGES);
+
+        findViewById(R.id.allow).setOnClickListener(this);
+        findViewById(R.id.deny).setOnClickListener(this);
+
+        TextView messageView = (TextView) getWindow().findViewById(R.id.message);
+        String authTokenLabel = getIntent().getExtras().getString(EXTRAS_AUTH_TOKEN_LABEL);
+        if (authTokenLabel.length() == 0) {
+            CharSequence grantCredentialsPermissionFormat = getResources().getText(
+                    R.string.grant_credentials_permission_message_desc);
+            messageView.setText(String.format(grantCredentialsPermissionFormat.toString(),
+                    mAccount.mName, accountTypeLabel));
+        } else {
+            CharSequence grantCredentialsPermissionFormat = getResources().getText(
+                    R.string.grant_credentials_permission_message_with_authtokenlabel_desc);
+            messageView.setText(String.format(grantCredentialsPermissionFormat.toString(),
+                    authTokenLabel, mAccount.mName, accountTypeLabel));
+        }
+
+        String[] packageLabels = new String[packages.length];
+        final PackageManager pm = getPackageManager();
+        for (int i = 0; i < packages.length; i++) {
+            try {
+                packageLabels[i] =
+                        pm.getApplicationLabel(pm.getApplicationInfo(packages[i], 0)).toString();
+            } catch (PackageManager.NameNotFoundException e) {
+                packageLabels[i] = packages[i];
+            }
+        }
+        ((ListView) findViewById(R.id.packages_list)).setAdapter(
+                new PackagesArrayAdapter(this, packageLabels));
+    }
+
+    public void onClick(View v) {
+        switch (v.getId()) {
+            case R.id.allow:
+                AccountManagerService.getSingleton().grantAppPermission(mAccount, mAuthTokenType,
+                        mUid);
+                Intent result = new Intent();
+                result.putExtra("retry", true);
+                setResult(RESULT_OK, result);
+                setAccountAuthenticatorResult(result.getExtras());
+                break;
+
+            case R.id.deny:
+                AccountManagerService.getSingleton().revokeAppPermission(mAccount, mAuthTokenType,
+                        mUid);
+                setResult(RESULT_CANCELED);
+                break;
+        }
+        finish();
+    }
+
+    public final void setAccountAuthenticatorResult(Bundle result) {
+        mResultBundle = result;
+    }
+
+    /**
+     * Sends the result or a Constants.ERROR_CODE_CANCELED error if a result isn't present.
+     */
+    public void finish() {
+        Intent intent = getIntent();
+        AccountAuthenticatorResponse accountAuthenticatorResponse =
+                intent.getParcelableExtra(EXTRAS_RESPONSE);
+        if (accountAuthenticatorResponse != null) {
+            // send the result bundle back if set, otherwise send an error.
+            if (mResultBundle != null) {
+                accountAuthenticatorResponse.onResult(mResultBundle);
+            } else {
+                accountAuthenticatorResponse.onError(Constants.ERROR_CODE_CANCELED, "canceled");
+            }
+        }
+        super.finish();
+    }
+
+    private static class PackagesArrayAdapter extends ArrayAdapter<String> {
+        protected LayoutInflater mInflater;
+        private static final int mResource = R.layout.simple_list_item_1;
+
+        public PackagesArrayAdapter(Context context, String[] items) {
+            super(context, mResource, items);
+            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        }
+
+        static class ViewHolder {
+            TextView label;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            // A ViewHolder keeps references to children views to avoid unneccessary calls
+            // to findViewById() on each row.
+            ViewHolder holder;
+
+            // When convertView is not null, we can reuse it directly, there is no need
+            // to reinflate it. We only inflate a new View when the convertView supplied
+            // by ListView is null.
+            if (convertView == null) {
+                convertView = mInflater.inflate(mResource, null);
+
+                // Creates a ViewHolder and store references to the two children views
+                // we want to bind data to.
+                holder = new ViewHolder();
+                holder.label = (TextView) convertView.findViewById(R.id.text1);
+
+                convertView.setTag(holder);
+            } else {
+                // Get the ViewHolder back to get fast access to the TextView
+                // and the ImageView.
+                holder = (ViewHolder) convertView.getTag();
+            }
+
+            holder.label.setText(getItem(position));
+
+            return convertView;
+        }
+    }
+}
diff --git a/core/java/android/accounts/IAccountAuthenticator.aidl b/core/java/android/accounts/IAccountAuthenticator.aidl
index 46a7144..7d4de39 100644
--- a/core/java/android/accounts/IAccountAuthenticator.aidl
+++ b/core/java/android/accounts/IAccountAuthenticator.aidl
@@ -49,6 +49,11 @@
         String authTokenType, in Bundle options);
 
     /**
+     * Gets the user-visible label of the given authtoken type.
+     */
+    void getAuthTokenLabel(in IAccountAuthenticatorResponse response, String authTokenType);
+
+    /**
      * prompts the user for a new password and writes it to the IAccountManager
      */
     void updateCredentials(in IAccountAuthenticatorResponse response, in Account account,
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 76b47f1..182843a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -177,11 +177,17 @@
         synchronized (mPackages) {
             // Resources is app scale dependent.
             ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
-            //Log.w(TAG, "getTopLevelResources: " + resDir);
+            if (false) {
+                Log.w(TAG, "getTopLevelResources: " + resDir + " / "
+                        + compInfo.applicationScale);
+            }
             WeakReference<Resources> wr = mActiveResources.get(key);
             Resources r = wr != null ? wr.get() : null;
             if (r != null && r.getAssets().isUpToDate()) {
-                //Log.w(TAG, "Returning cached resources " + r + " " + resDir);
+                if (false) {
+                    Log.w(TAG, "Returning cached resources " + r + " " + resDir
+                            + ": appScale=" + r.getCompatibilityInfo().applicationScale);
+                }
                 return r;
             }
 
@@ -198,7 +204,11 @@
             //Log.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
             DisplayMetrics metrics = getDisplayMetricsLocked(false);
             r = new Resources(assets, metrics, getConfiguration(), compInfo);
-            //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration());
+            if (false) {
+                Log.i(TAG, "Created app resources " + resDir + " " + r + ": "
+                        + r.getConfiguration() + " appScale="
+                        + r.getCompatibilityInfo().applicationScale);
+            }
             // XXX need to remove entries when weak references go away
             mActiveResources.put(key, new WeakReference<Resources>(r));
             return r;
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index ae9e380..1e4ab68 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -544,7 +544,10 @@
             if (fd != null) {
                 Bitmap bm = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor());
                 if (bm != null) {
-                    return new BitmapDrawable(bm);
+                    // For now clear the density until we figure out how
+                    // to deal with it for wallpapers.
+                    bm.setDensity(0);
+                    return new BitmapDrawable(getResources(), bm);
                 }
             }
         } catch (RemoteException e) {
@@ -1965,6 +1968,15 @@
             try {
                 Resources r = getResourcesForApplication(appInfo);
                 dr = r.getDrawable(resid);
+                if (false) {
+                    RuntimeException e = new RuntimeException("here");
+                    e.fillInStackTrace();
+                    Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
+                            + " from package " + packageName
+                            + ": app scale=" + r.getCompatibilityInfo().applicationScale
+                            + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
+                            e);
+                }
                 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
                         + Integer.toHexString(resid) + " from " + r
                         + ": " + dr);
@@ -2052,10 +2064,9 @@
             if (app.packageName.equals("system")) {
                 return mContext.mMainThread.getSystemContext().getResources();
             }
-            ActivityThread.PackageInfo pi = mContext.mMainThread.getPackageInfoNoCheck(app);
             Resources r = mContext.mMainThread.getTopLevelResources(
                     app.uid == Process.myUid() ? app.sourceDir
-                    : app.publicSourceDir, pi);
+                    : app.publicSourceDir, mContext.mPackageInfo);
             if (r != null) {
                 return r;
             }
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index a3c6325..5335239 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -524,7 +524,8 @@
         data.writeInterfaceToken(IApplicationThread.descriptor);
         app.writeToParcel(data, 0);
         data.writeInt(backupMode);
-        mRemote.transact(SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION, data, null, 0);
+        mRemote.transact(SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION, data, null,
+                IBinder.FLAG_ONEWAY);
         data.recycle();
     }
 
@@ -532,7 +533,8 @@
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         app.writeToParcel(data, 0);
-        mRemote.transact(SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION, data, null, 0);
+        mRemote.transact(SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION, data, null,
+                IBinder.FLAG_ONEWAY);
         data.recycle();
     }
     
diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java
index accdda9..d788c43 100644
--- a/core/java/android/app/LauncherActivity.java
+++ b/core/java/android/app/LauncherActivity.java
@@ -297,7 +297,7 @@
                     icon.setBounds(x, y, x + width, y + height);
                     icon.draw(canvas);
                     icon.setBounds(mOldBounds);
-                    icon = new BitmapDrawable(thumb);
+                    icon = new BitmapDrawable(getResources(), thumb);
                 } else if (iconWidth < width && iconHeight < height) {
                     final Bitmap.Config c = Bitmap.Config.ARGB_8888;
                     final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
@@ -309,7 +309,7 @@
                     icon.setBounds(x, y, x + iconWidth, y + iconHeight);
                     icon.draw(canvas);
                     icon.setBounds(mOldBounds);
-                    icon = new BitmapDrawable(thumb);
+                    icon = new BitmapDrawable(getResources(), thumb);
                 }
             }
 
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 27c6376..dd70130 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -34,7 +34,10 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
 import android.os.SystemClock;
+import android.provider.Browser;
 import android.server.search.SearchableInfo;
 import android.speech.RecognizerIntent;
 import android.text.Editable;
@@ -42,6 +45,7 @@
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.text.util.Regex;
+import android.util.AndroidRuntimeException;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
@@ -537,6 +541,8 @@
             mSearchAutoComplete.setDropDownAlwaysVisible(false);
         }
 
+        mSearchAutoComplete.setForceIgnoreOutsideTouch(true);
+
         // attach the suggestions adapter, if suggestions are available
         // The existence of a suggestions authority is the proxy for "suggestions available here"
         if (mSearchable.getSuggestAuthority() != null) {
@@ -794,7 +800,6 @@
             
             if (!event.isSystem() && 
                     (keyCode != KeyEvent.KEYCODE_DPAD_UP) &&
-                    (keyCode != KeyEvent.KEYCODE_DPAD_DOWN) &&
                     (keyCode != KeyEvent.KEYCODE_DPAD_LEFT) &&
                     (keyCode != KeyEvent.KEYCODE_DPAD_RIGHT) &&
                     (keyCode != KeyEvent.KEYCODE_DPAD_CENTER)) {
@@ -1093,7 +1098,8 @@
      */
     protected void launchQuerySearch(int actionKey, String actionMsg)  {
         String query = mSearchAutoComplete.getText().toString();
-        Intent intent = createIntent(Intent.ACTION_SEARCH, null, null, query, null,
+        String action = mGlobalSearchMode ? Intent.ACTION_WEB_SEARCH : Intent.ACTION_SEARCH;
+        Intent intent = createIntent(action, null, null, query, null,
                 actionKey, actionMsg);
         launchIntent(intent);
     }
@@ -1245,16 +1251,127 @@
             return;
         }
         Log.d(LOG_TAG, "launching " + intent);
-        getContext().startActivity(intent);
-
-        // in global search mode, SearchDialogWrapper#performActivityResuming will handle hiding
-        // the dialog when the next activity starts, but for in-app search, we still need to
-        // dismiss the dialog.
-        if (!mGlobalSearchMode) {
-            dismiss();
+        try {
+            // in global search mode, we send the activity straight to the original suggestion
+            // source. this is because GlobalSearch may not have permission to launch the
+            // intent, and to avoid the extra step of going through GlobalSearch.
+            if (mGlobalSearchMode) {
+                launchGlobalSearchIntent(intent);
+            } else {
+                getContext().startActivity(intent);
+                // in global search mode, SearchDialogWrapper#performActivityResuming
+                // will handle hiding the dialog when the next activity starts, but for
+                // in-app search, we still need to dismiss the dialog.
+                dismiss();
+            }
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "Failed launch activity: " + intent, ex);
         }
     }
-    
+
+    private void launchGlobalSearchIntent(Intent intent) {
+        final String packageName;
+        // GlobalSearch puts the original source of the suggestion in the
+        // 'component name' column. If set, we send the intent to that activity.
+        // We trust GlobalSearch to always set this to the suggestion source.
+        String intentComponent = intent.getStringExtra(SearchManager.COMPONENT_NAME_KEY);
+        if (intentComponent != null) {
+            ComponentName componentName = ComponentName.unflattenFromString(intentComponent);
+            intent.setComponent(componentName);
+            intent.removeExtra(SearchManager.COMPONENT_NAME_KEY);
+            // Launch the intent as the suggestion source.
+            // This prevents sources from using the search dialog to launch
+            // intents that they don't have permission for themselves.
+            packageName = componentName.getPackageName();
+        } else {
+            // If there is no component in the suggestion, it must be a built-in suggestion
+            // from GlobalSearch (e.g. "Search the web for") or the intent
+            // launched when pressing the search/go button in the search dialog.
+            // Launch the intent with the permissions of GlobalSearch.
+            packageName = mSearchable.getSearchActivity().getPackageName();
+        }
+
+        // Launch all global search suggestions as new tasks, since they don't relate
+        // to the current task.
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        setBrowserApplicationId(intent);
+
+        if (DBG) Log.d(LOG_TAG, "Launching intent " + intent.toURI() + " as " + packageName);
+        startActivityInPackage(intent, packageName);
+    }
+
+    /**
+     * If the intent is to open an HTTP or HTTPS URL, we set
+     * {@link Browser#EXTRA_APPLICATION_ID} so that any existing browser window that
+     * has been opened by us for the same URL will be reused.
+     */
+    private void setBrowserApplicationId(Intent intent) {
+        Uri data = intent.getData();
+        if (Intent.ACTION_VIEW.equals(intent.getAction()) && data != null) {
+            String scheme = data.getScheme();
+            if (scheme != null && scheme.startsWith("http")) {
+                intent.putExtra(Browser.EXTRA_APPLICATION_ID, data.toString());
+            }
+        }
+    }
+
+    /**
+     * Starts an activity as if it had been started by the given package.
+     *
+     * @param intent The description of the activity to start.
+     * @param packageName
+     * @throws ActivityNotFoundException If the intent could not be resolved to
+     *         and existing activity.
+     * @throws SecurityException If the package does not have permission to start
+     *         start the activity.
+     * @throws AndroidRuntimeException If some other error occurs.
+     */
+    private void startActivityInPackage(Intent intent, String packageName) {
+        try {
+            int uid = ActivityThread.getPackageManager().getPackageUid(packageName);
+            if (uid < 0) {
+                throw new AndroidRuntimeException("Package UID not found " + packageName);
+            }
+            String resolvedType = intent.resolveTypeIfNeeded(getContext().getContentResolver());
+            IBinder resultTo = null;
+            String resultWho = null;
+            int requestCode = -1;
+            boolean onlyIfNeeded = false;
+            int result = ActivityManagerNative.getDefault().startActivityInPackage(
+                    uid, intent, resolvedType, resultTo, resultWho, requestCode, onlyIfNeeded);
+            checkStartActivityResult(result, intent);
+        } catch (RemoteException ex) {
+            throw new AndroidRuntimeException(ex);
+        }
+    }
+
+    // Stolen from Instrumentation.checkStartActivityResult()
+    private static void checkStartActivityResult(int res, Intent intent) {
+        if (res >= IActivityManager.START_SUCCESS) {
+            return;
+        }
+        switch (res) {
+            case IActivityManager.START_INTENT_NOT_RESOLVED:
+            case IActivityManager.START_CLASS_NOT_FOUND:
+                if (intent.getComponent() != null)
+                    throw new ActivityNotFoundException(
+                            "Unable to find explicit activity class "
+                            + intent.getComponent().toShortString()
+                            + "; have you declared this activity in your AndroidManifest.xml?");
+                throw new ActivityNotFoundException(
+                        "No Activity found to handle " + intent);
+            case IActivityManager.START_PERMISSION_DENIED:
+                throw new SecurityException("Not allowed to start activity "
+                        + intent);
+            case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
+                throw new AndroidRuntimeException(
+                        "FORWARD_RESULT_FLAG used while also requesting a result");
+            default:
+                throw new AndroidRuntimeException("Unknown error code "
+                        + res + " when starting " + intent);
+        }
+    }
+
     /**
      * Handles the special intent actions declared in {@link SearchManager}.
      * 
@@ -1460,8 +1577,10 @@
             intent.putExtra(SearchManager.ACTION_KEY, actionKey);
             intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
         }
-        // attempt to enforce security requirement (no 3rd-party intents)
-        intent.setComponent(mSearchable.getSearchActivity());
+        // Only allow 3rd-party intents from GlobalSearch
+        if (!mGlobalSearchMode) {
+            intent.setComponent(mSearchable.getSearchActivity());
+        }
         return intent;
     }
     
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 0631ad5..fd559d6 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1215,18 +1215,13 @@
                 = "DialogCursorProtocol.POST_REFRESH.displayNotify";
 
         /**
-         * Just before closing the cursor.
-         */
-        public final static int PRE_CLOSE = 1;
-        public final static String PRE_CLOSE_SEND_MAX_DISPLAY_POS
-                = "DialogCursorProtocol.PRE_CLOSE.sendDisplayPosition";
-
-        /**
          * When a position has been clicked.
          */
         public final static int CLICK = 2;
         public final static String CLICK_SEND_POSITION
                 = "DialogCursorProtocol.CLICK.sendPosition";
+        public final static String CLICK_SEND_MAX_DISPLAY_POS
+                = "DialogCursorProtocol.CLICK.sendDisplayPosition";
         public final static String CLICK_RECEIVE_SELECTED_POS
                 = "DialogCursorProtocol.CLICK.receiveSelectedPosition";
 
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 593b7b7..4a00e48 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -27,6 +27,7 @@
 import android.database.Cursor;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableContainer;
 import android.graphics.drawable.StateListDrawable;
 import android.net.Uri;
 import android.os.Bundle;
@@ -135,6 +136,8 @@
             private int mPreviousLength = 0;
 
             public long getPostingDelay(CharSequence constraint) {
+                if (constraint == null) return 0;
+                
                 long delay = constraint.length() < mPreviousLength ? DELETE_KEY_POST_DELAY : 0;
                 mPreviousLength = constraint.length();
                 return delay;
@@ -191,35 +194,19 @@
     public void changeCursor(Cursor c) {
         if (DBG) Log.d(LOG_TAG, "changeCursor(" + c + ")");
 
-        if (mCursor != null) {
-            callCursorPreClose(mCursor);
+        try {
+            super.changeCursor(c);
+            if (c != null) {
+                mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
+                mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
+                mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
+                mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
+                mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
+                mBackgroundColorCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_BACKGROUND_COLOR);
+            }
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "error changing cursor and caching columns", e);
         }
-
-        super.changeCursor(c);
-        if (c != null) {
-            mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
-            mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
-            mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
-            mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
-            mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
-            mBackgroundColorCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_BACKGROUND_COLOR);
-        }
-    }
-
-    /**
-     * Handle sending and receiving information associated with
-     * {@link DialogCursorProtocol#PRE_CLOSE}.
-     *
-     * @param cursor The cursor to call.
-     */
-    private void callCursorPreClose(Cursor cursor) {
-        if (!mGlobalSearchMode) return;
-        final Bundle request = new Bundle();
-        request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.PRE_CLOSE);
-        request.putInt(DialogCursorProtocol.PRE_CLOSE_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
-        final Bundle response = cursor.respond(request);
-
-        mMaxDisplayed = -1;
     }
 
     @Override
@@ -267,7 +254,9 @@
         final Bundle request = new Bundle(1);
         request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK);
         request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position);
+        request.putInt(DialogCursorProtocol.CLICK_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
         final Bundle response = cursor.respond(request);
+        mMaxDisplayed = -1;
         mListItemToSelect = response.getInt(
                 DialogCursorProtocol.CLICK_RECEIVE_SELECTED_POS, SuggestionsAdapter.NONE);
     }
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
new file mode 100644
index 0000000..d6044145
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2008 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.bluetooth;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.RemoteException;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+
+/**
+ * The Android Bluetooth API is not finalized, and *will* change. Use at your
+ * own risk.
+ *
+ * Public API for controlling the Bluetooth Pbap Service. This includes
+ * Bluetooth Phone book Access profile.
+ * BluetoothPbap is a proxy object for controlling the Bluetooth Pbap
+ * Service via IPC.
+ *
+ * Creating a BluetoothPbap object will create a binding with the
+ * BluetoothPbap service. Users of this object should call close() when they
+ * are finished with the BluetoothPbap, so that this proxy object can unbind
+ * from the service.
+ *
+ * This BluetoothPbap object is not immediately bound to the
+ * BluetoothPbap service. Use the ServiceListener interface to obtain a
+ * notification when it is bound, this is especially important if you wish to
+ * immediately call methods on BluetoothPbap after construction.
+ *
+ * Android only supports one connected Bluetooth Pce at a time.
+ *
+ * @hide
+ */
+public class BluetoothPbap {
+
+    private static final String TAG = "BluetoothPbap";
+    private static final boolean DBG = false;
+
+    /** int extra for PBAP_STATE_CHANGED_ACTION */
+    public static final String PBAP_STATE =
+        "android.bluetooth.pbap.intent.PBAP_STATE";
+    /** int extra for PBAP_STATE_CHANGED_ACTION */
+    public static final String PBAP_PREVIOUS_STATE =
+        "android.bluetooth.pbap.intent.PBAP_PREVIOUS_STATE";
+
+    /** Indicates the state of an pbap connection state has changed.
+     *  This intent will always contain PBAP_STATE, PBAP_PREVIOUS_STATE and
+     *  BluetoothIntent.ADDRESS extras.
+     */
+    public static final String PBAP_STATE_CHANGED_ACTION =
+        "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED";
+
+    private IBluetoothPbap mService;
+    private final Context mContext;
+    private final ServiceListener mServiceListener;
+
+    /** There was an error trying to obtain the state */
+    public static final int STATE_ERROR        = -1;
+    /** No headset currently connected */
+    public static final int STATE_DISCONNECTED = 0;
+    /** Connection attempt in progress */
+    public static final int STATE_CONNECTING   = 1;
+    /** A headset is currently connected */
+    public static final int STATE_CONNECTED    = 2;
+
+    public static final int RESULT_FAILURE = 0;
+    public static final int RESULT_SUCCESS = 1;
+    /** Connection canceled before completion. */
+    public static final int RESULT_CANCELED = 2;
+
+    public static final int PRIORITY_AUTO = 100;
+    public static final int PRIORITY_OFF = 0;
+    /**
+     * An interface for notifying Bluetooth PCE IPC clients when they have
+     * been connected to the BluetoothHeadset service.
+     */
+    public interface ServiceListener {
+        /**
+         * Called to notify the client when this proxy object has been
+         * connected to the BluetoothPbap service. Clients must wait for
+         * this callback before making IPC calls on the BluetoothPbap
+         * service.
+         */
+        public void onServiceConnected();
+
+        /**
+         * Called to notify the client that this proxy object has been
+         * disconnected from the BluetoothPbap service. Clients must not
+         * make IPC calls on the BluetoothPbap service after this callback.
+         * This callback will currently only occur if the application hosting
+         * the BluetoothPbap service, but may be called more often in future.
+         */
+        public void onServiceDisconnected();
+    }
+
+    /**
+     * Create a BluetoothHeadset proxy object.
+     */
+    public BluetoothPbap(Context context, ServiceListener l) {
+        mContext = context;
+        mServiceListener = l;
+        if (!context.bindService(new Intent(IBluetoothPbap.class.getName()), mConnection, 0)) {
+            Log.e(TAG, "Could not bind to Bluetooth Pbap Service");
+        }
+    }
+
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Close the connection to the backing service.
+     * Other public functions of BluetoothHeadset will return default error
+     * results once close() has been called. Multiple invocations of close()
+     * are ok.
+     */
+    public synchronized void close() {
+        if (mConnection != null) {
+            mContext.unbindService(mConnection);
+            mConnection = null;
+        }
+    }
+
+    /**
+     * Get the current state of the Bluetooth Headset service.
+     * @return One of the STATE_ return codes, or STATE_ERROR if this proxy
+     *         object is currently not connected to the Headset service.
+     */
+    public int getState() {
+        if (DBG) log("getState()");
+        if (mService != null) {
+            try {
+                return mService.getState();
+            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) log(Log.getStackTraceString(new Throwable()));
+        }
+        return BluetoothHeadset.STATE_ERROR;
+    }
+
+    /**
+     * Get the Bluetooth address of the current headset.
+     * @return The Bluetooth address, or null if not in connected or connecting
+     *         state, or if this proxy object is not connected to the Headset
+     *         service.
+     */
+    public String getPceAddress() {
+        if (DBG) log("getPceAddress()");
+        if (mService != null) {
+            try {
+                return mService.getPceAddress();
+            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) log(Log.getStackTraceString(new Throwable()));
+        }
+        return null;
+    }
+
+    /**
+     * Returns true if the specified headset is connected (does not include
+     * connecting). Returns false if not connected, or if this proxy object
+     * if not currently connected to the headset service.
+     */
+    public boolean isConnected(String address) {
+        if (DBG) log("isConnected(" + address + ")");
+        if (mService != null) {
+            try {
+                return mService.isConnected(address);
+            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) log(Log.getStackTraceString(new Throwable()));
+        }
+        return false;
+    }
+
+    /**
+     * Disconnects the current headset. Currently this call blocks, it may soon
+     * be made asynchornous. Returns false if this proxy object is
+     * not currently connected to the Headset service.
+     */
+    public boolean disconnectPce() {
+        if (DBG) log("disconnectPce()");
+        if (mService != null) {
+            try {
+                mService.disconnectPce();
+                return true;
+            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) log(Log.getStackTraceString(new Throwable()));
+        }
+        return false;
+    }
+
+    /**
+     * Check class bits for possible PBAP support.
+     * This is a simple heuristic that tries to guess if a device with the
+     * given class bits might support PBAP. It is not accurate for all
+     * devices. It tries to err on the side of false positives.
+     * @return True if this device might support PBAP.
+     */
+    public static boolean doesClassMatchSink(int btClass) {
+        // TODO optimize the rule
+        switch (BluetoothClass.Device.getDevice(btClass)) {
+        case BluetoothClass.Device.COMPUTER_DESKTOP:
+        case BluetoothClass.Device.COMPUTER_LAPTOP:
+        case BluetoothClass.Device.COMPUTER_SERVER:
+        case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) log("Proxy object connected");
+            mService = IBluetoothPbap.Stub.asInterface(service);
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected();
+            }
+        }
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) log("Proxy object disconnected");
+            mService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected();
+            }
+        }
+    };
+
+    private static void log(String msg) {
+        Log.d(TAG, msg);
+    }
+}
diff --git a/core/java/android/bluetooth/IBluetoothPbap.aidl b/core/java/android/bluetooth/IBluetoothPbap.aidl
new file mode 100644
index 0000000..06cdb7b
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothPbap.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2008 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.bluetooth;
+
+/**
+ * System private API for Bluetooth pbap service
+ *
+ * {@hide}
+ */
+interface IBluetoothPbap {
+    int getState();
+    String getPceAddress();
+    boolean connectPce(in String address);
+    void disconnectPce();
+    boolean isConnected(in String address);
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 4a3137f..9ca11cd 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -169,21 +169,22 @@
     public static final int FLAG_RESIZEABLE_FOR_SCREENS = 1<<12;
     
     /**
+     * Value for {@link #flags}: true when the application knows how to
+     * accomodate different screen densities.  Corresponds to
+     * {@link android.R.styleable#AndroidManifestSupportsScreens_anyDensity
+     * android:anyDensity}.
+     */
+    public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 1<<13;
+    
+    /**
      * Value for {@link #flags}: this is false if the application has set
      * its android:allowBackup to false, true otherwise.
      * 
      * {@hide}
      */
-    public static final int FLAG_ALLOW_BACKUP = 1<<13;
+    public static final int FLAG_ALLOW_BACKUP = 1<<14;
     
     /**
-     * Indicates that the application supports any densities;
-     * {@hide}
-     */
-    public static final int ANY_DENSITY = -1;
-    static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY };
-
-    /**
      * Flags associated with the application.  Any combination of
      * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
      * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
@@ -228,13 +229,6 @@
     public int uid;
     
     /**
-     * The list of densities in DPI that application supprots. This
-     * field is only set if the {@link PackageManager#GET_SUPPORTS_DENSITIES} flag was
-     * used when retrieving the structure.
-     */
-    public int[] supportsDensities;
-
-    /**
      * The minimum SDK version this application targets.  It may run on earilier
      * versions, but it knows how to work with any new behavior added at this
      * version.  Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
@@ -267,7 +261,6 @@
         pw.println(prefix + "enabled=" + enabled);
         pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
         pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));
-        pw.println(prefix + "supportsDensities=" + supportsDensities);
         super.dumpBack(pw, prefix);
     }
     
@@ -314,7 +307,6 @@
         enabled = orig.enabled;
         manageSpaceActivityName = orig.manageSpaceActivityName;
         descriptionRes = orig.descriptionRes;
-        supportsDensities = orig.supportsDensities;
     }
 
 
@@ -346,7 +338,6 @@
         dest.writeString(manageSpaceActivityName);
         dest.writeString(backupAgentName);
         dest.writeInt(descriptionRes);
-        dest.writeIntArray(supportsDensities);
     }
 
     public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -377,7 +368,6 @@
         manageSpaceActivityName = source.readString();
         backupAgentName = source.readString();
         descriptionRes = source.readInt();
-        supportsDensities = source.createIntArray();
     }
 
     /**
@@ -408,7 +398,7 @@
      */
     public void disableCompatibilityMode() {
         flags |= (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS |
-                FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS);
-        supportsDensities = ANY_DENSITIES_ARRAY;
+                FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS |
+                FLAG_SUPPORTS_SCREEN_DENSITIES);
     }
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3250a87..bca1715 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -165,12 +165,6 @@
     public static final int GET_CONFIGURATIONS = 0x00004000;
 
     /**
-     * {@link ApplicationInfo} flag: return the
-     * {@link ApplicationInfo#supportsDensities} that the package supports.
-     */
-    public static final int GET_SUPPORTS_DENSITIES    = 0x00008000;
-
-    /**
      * Resolution and querying flag: if set, only filters that support the
      * {@link android.content.Intent#CATEGORY_DEFAULT} will be considered for
      * matching.  This is a synonym for including the CATEGORY_DEFAULT in your
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 93ba959..33f4b52 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -675,6 +675,7 @@
         int supportsNormalScreens = 1;
         int supportsLargeScreens = 1;
         int resizeable = 1;
+        int anyDensity = 1;
         
         int outerDepth = parser.getDepth();
         while ((type=parser.next()) != parser.END_DOCUMENT
@@ -854,21 +855,6 @@
 
                 XmlUtils.skipCurrentTag(parser);
 
-            } else if (tagName.equals("supports-density")) {
-                sa = res.obtainAttributes(attrs,
-                        com.android.internal.R.styleable.AndroidManifestSupportsDensity);
-
-                int density = sa.getInteger(
-                        com.android.internal.R.styleable.AndroidManifestSupportsDensity_density, -1);
-
-                sa.recycle();
-
-                if (density != -1 && !pkg.supportsDensityList.contains(density)) {
-                    pkg.supportsDensityList.add(density);
-                }
-
-                XmlUtils.skipCurrentTag(parser);
-
             } else if (tagName.equals("supports-screens")) {
                 sa = res.obtainAttributes(attrs,
                         com.android.internal.R.styleable.AndroidManifestSupportsScreens);
@@ -887,6 +873,9 @@
                 resizeable = sa.getInteger(
                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
                         supportsLargeScreens);
+                anyDensity = sa.getInteger(
+                        com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
+                        anyDensity);
 
                 sa.recycle();
                 
@@ -962,7 +951,7 @@
         
         if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
                 && pkg.applicationInfo.targetSdkVersion
-                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
+                        >= android.os.Build.VERSION_CODES.DONUT)) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
         }
         if (supportsNormalScreens != 0) {
@@ -970,32 +959,19 @@
         }
         if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
                 && pkg.applicationInfo.targetSdkVersion
-                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
+                        >= android.os.Build.VERSION_CODES.DONUT)) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
         }
         if (resizeable < 0 || (resizeable > 0
                 && pkg.applicationInfo.targetSdkVersion
-                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
+                        >= android.os.Build.VERSION_CODES.DONUT)) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
         }
-        int densities[] = null;
-        int size = pkg.supportsDensityList.size();
-        if (size > 0) {
-            densities = pkg.supportsDensities = new int[size];
-            List<Integer> densityList = pkg.supportsDensityList;
-            for (int i = 0; i < size; i++) {
-                densities[i] = densityList.get(i);
-            }
+        if (anyDensity < 0 || (anyDensity > 0
+                && pkg.applicationInfo.targetSdkVersion
+                        >= android.os.Build.VERSION_CODES.DONUT)) {
+            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
         }
-        /**
-         * TODO: enable this before code freeze. b/1967935
-         * *
-        if ((densities == null || densities.length == 0)
-                && (pkg.applicationInfo.targetSdkVersion
-                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
-            pkg.supportsDensities = ApplicationInfo.ANY_DENSITIES_ARRAY;
-        }
-         */
 
         return pkg;
     }
@@ -2446,9 +2422,6 @@
         // We store the application meta-data independently to avoid multiple unwanted references
         public Bundle mAppMetaData = null;
 
-        public final ArrayList<Integer> supportsDensityList = new ArrayList<Integer>();
-        public int[] supportsDensities = null;
-
         // If this is a 3rd party app, this is the path of the zip file.
         public String mPath;
 
@@ -2630,10 +2603,6 @@
                 && p.usesLibraryFiles != null) {
             return true;
         }
-        if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0
-                && p.supportsDensities != null) {
-            return true;
-        }
         return false;
     }
 
@@ -2656,9 +2625,6 @@
         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
             ai.sharedLibraryFiles = p.usesLibraryFiles;
         }
-        if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0) {
-            ai.supportsDensities = p.supportsDensities;
-        }
         if (!sCompatibilityModeEnabled) {
             ai.disableCompatibilityMode();
         }
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index bb94372..342de2b 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -114,10 +114,12 @@
     public static class ServiceInfo<V> {
         public final V type;
         public final ComponentName componentName;
+        public final int uid;
 
-        private ServiceInfo(V type, ComponentName componentName) {
+        private ServiceInfo(V type, ComponentName componentName, int uid) {
             this.type = type;
             this.componentName = componentName;
+            this.uid = uid;
         }
 
         public String toString() {
@@ -223,7 +225,10 @@
             if (v == null) {
                 return null;
             }
-            return new ServiceInfo<V>(v, componentName);
+            final android.content.pm.ServiceInfo serviceInfo = service.serviceInfo;
+            final ApplicationInfo applicationInfo = serviceInfo.applicationInfo;
+            final int uid = applicationInfo.uid;
+            return new ServiceInfo<V>(v, componentName, uid);
         } finally {
             if (parser != null) parser.close();
         }
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 517551e..50faf57 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -131,41 +131,15 @@
             mCompatibilityFlags |= EXPANDABLE | CONFIGURED_EXPANDABLE;
         }
         
-        float packageDensityScale = -1.0f;
-        int packageDensity = 0;
-        if (appInfo.supportsDensities != null) {
-            int minDiff = Integer.MAX_VALUE;
-            for (int density : appInfo.supportsDensities) {
-                if (density == ApplicationInfo.ANY_DENSITY) {
-                    packageDensity = DisplayMetrics.DENSITY_DEVICE;
-                    packageDensityScale = 1.0f;
-                    break;
-                }
-                int tmpDiff = Math.abs(DisplayMetrics.DENSITY_DEVICE - density);
-                if (tmpDiff == 0) {
-                    packageDensity = DisplayMetrics.DENSITY_DEVICE;
-                    packageDensityScale = 1.0f;
-                    break;
-                }
-                // prefer higher density (appScale>1.0), unless that's only option.
-                if (tmpDiff < minDiff && packageDensityScale < 1.0f) {
-                    packageDensity = density;
-                    packageDensityScale = DisplayMetrics.DENSITY_DEVICE / (float) density;
-                    minDiff = tmpDiff;
-                }
-            }
-        }
-        if (packageDensityScale > 0.0f) {
-            applicationDensity = packageDensity;
-            applicationScale = packageDensityScale;
+        if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
+            applicationDensity = DisplayMetrics.DENSITY_DEVICE;
+            applicationScale = 1.0f;
+            applicationInvertedScale = 1.0f;
         } else {
             applicationDensity = DisplayMetrics.DENSITY_DEFAULT;
-            applicationScale =
-                    DisplayMetrics.DENSITY_DEVICE / (float) DisplayMetrics.DENSITY_DEFAULT;
-        }
-
-        applicationInvertedScale = 1.0f / applicationScale;
-        if (applicationScale != 1.0f) {
+            applicationScale = DisplayMetrics.DENSITY_DEVICE
+                    / (float) DisplayMetrics.DENSITY_DEFAULT;
+            applicationInvertedScale = 1.0f / applicationScale;
             mCompatibilityFlags |= SCALING_REQUIRED;
         }
     }
@@ -254,20 +228,11 @@
     }
 
     /**
-     * Returns the translator which can translate the coordinates of the window.
-     * There are five different types of Translator.
+     * Returns the translator which translates the coordinates in compatibility mode.
      * @param params the window's parameter
      */
-    public Translator getTranslator(WindowManager.LayoutParams params) {
-        if ( (mCompatibilityFlags & SCALING_EXPANDABLE_MASK)
-                == (EXPANDABLE|LARGE_SCREENS)) {
-            if (DBG) Log.d(TAG, "no translation required");
-            return null;
-        }
-        if (!isScalingRequired()) {
-            return null;
-        }
-        return new Translator();
+    public Translator getTranslator() {
+        return isScalingRequired() ? new Translator() : null;
     }
 
     /**
diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java
index cf5a573..d5c3a32 100644
--- a/core/java/android/database/MatrixCursor.java
+++ b/core/java/android/database/MatrixCursor.java
@@ -214,53 +214,64 @@
 
     // AbstractCursor implementation.
 
+    @Override
     public int getCount() {
         return rowCount;
     }
 
+    @Override
     public String[] getColumnNames() {
         return columnNames;
     }
 
+    @Override
     public String getString(int column) {
-        return String.valueOf(get(column));
+        Object value = get(column);
+        if (value == null) return null;
+        return value.toString();
     }
 
+    @Override
     public short getShort(int column) {
         Object value = get(column);
-        return (value instanceof String)
-                ? Short.valueOf((String) value)
-                : ((Number) value).shortValue();
+        if (value == null) return 0;
+        if (value instanceof Number) return ((Number) value).shortValue();
+        return Short.parseShort(value.toString());
     }
 
+    @Override
     public int getInt(int column) {
         Object value = get(column);
-        return (value instanceof String)
-                ? Integer.valueOf((String) value)
-                : ((Number) value).intValue();
+        if (value == null) return 0;
+        if (value instanceof Number) return ((Number) value).intValue();
+        return Integer.parseInt(value.toString());
     }
 
+    @Override
     public long getLong(int column) {
         Object value = get(column);
-        return (value instanceof String)
-                ? Long.valueOf((String) value)
-                : ((Number) value).longValue();
+        if (value == null) return 0;
+        if (value instanceof Number) return ((Number) value).longValue();
+        return Long.parseLong(value.toString());
     }
 
+    @Override
     public float getFloat(int column) {
         Object value = get(column);
-        return (value instanceof String)
-                ? Float.valueOf((String) value)
-                : ((Number) value).floatValue();
+        if (value == null) return 0.0f;
+        if (value instanceof Number) return ((Number) value).floatValue();
+        return Float.parseFloat(value.toString());
     }
 
+    @Override
     public double getDouble(int column) {
         Object value = get(column);
-        return (value instanceof String)
-                ? Double.valueOf((String) value)
-                : ((Number) value).doubleValue();
+        if (value == null) return 0.0d;
+        if (value instanceof Number) return ((Number) value).doubleValue();
+        return Double.parseDouble(value.toString());
     }
 
+    @Override
     public boolean isNull(int column) {
         return get(column) == null;
     }
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 7d331dc..184d6dc 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1412,8 +1412,9 @@
         StringBuilder sql = new StringBuilder(120);
         sql.append("UPDATE ");
         if (algorithm != null) {
-            sql.append(" OR ");
+            sql.append("OR ");
             sql.append(algorithm.value());
+            sql.append(" ");
         }
         
         sql.append(table);
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 7830cb7..4d6b7be9 100755
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -31,6 +31,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.view.GestureDetector;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -161,8 +162,8 @@
     private static final int MSG_REMOVE_PREVIEW = 2;
     private static final int MSG_REPEAT = 3;
     private static final int MSG_LONGPRESS = 4;
-    
-    private static final int DELAY_BEFORE_PREVIEW = 70;
+
+    private static final int DELAY_BEFORE_PREVIEW = 40;
     private static final int DELAY_AFTER_PREVIEW = 60;
     
     private int mVerticalCorrection;
@@ -827,10 +828,10 @@
             mPreviewText.setCompoundDrawables(null, null, null, null);
             mPreviewText.setText(getPreviewText(key));
             if (key.label.length() > 1 && key.codes.length < 2) {
-                mPreviewText.setTextSize(mKeyTextSize);
+                mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyTextSize);
                 mPreviewText.setTypeface(Typeface.DEFAULT_BOLD);
             } else {
-                mPreviewText.setTextSize(mPreviewTextSizeLarge);
+                mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mPreviewTextSizeLarge);
                 mPreviewText.setTypeface(Typeface.DEFAULT);
             }
         }
diff --git a/core/java/android/net/http/RequestQueue.java b/core/java/android/net/http/RequestQueue.java
index b6f295e..e14af66 100644
--- a/core/java/android/net/http/RequestQueue.java
+++ b/core/java/android/net/http/RequestQueue.java
@@ -561,9 +561,8 @@
 
         if (mNetworkConnected && mPending.containsKey(host)) {
             LinkedList<Request> reqList = mPending.get(host);
-            if (!reqList.isEmpty()) {
-                ret = reqList.removeFirst();
-            } else {
+            ret = reqList.removeFirst();
+            if (reqList.isEmpty()) {
                 mPending.remove(host);
             }
         }
@@ -624,9 +623,8 @@
         if (iter.hasNext()) {
             Map.Entry<HttpHost, LinkedList<Request>> entry = iter.next();
             LinkedList<Request> reqList = entry.getValue();
-            if (!reqList.isEmpty()) {
-                ret = reqList.removeFirst();
-            } else {
+            ret = reqList.removeFirst();
+            if (reqList.isEmpty()) {
                 requestQueue.remove(entry.getKey());
             }
         }
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d626751..70c7e63 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -113,7 +113,7 @@
         public static final String SEND_TO_VOICEMAIL = "send_to_voicemail";
     }
 
-    public interface AggregatesColumns {
+    private interface AggregatesColumns {
         /**
          * The display name for the contact.
          * <P>Type: TEXT</P>
@@ -143,8 +143,33 @@
          * any {@link GroupMembership} for this aggregate.
          */
         public static final String IN_VISIBLE_GROUP = "in_visible_group";
+
+        /**
+         * Contact presence status.  See {@link android.provider.Im.CommonPresenceColumns}
+         * for individual status definitions.
+         */
+        public static final String PRESENCE_STATUS = Presence.PRESENCE_STATUS;
+
+        /**
+         * The type of data, for example Home or Work.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String PRIMARY_PHONE_TYPE = CommonDataKinds.Phone.TYPE;
+
+        /**
+         * The user defined label for the primary phone.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PRIMARY_PHONE_LABEL = CommonDataKinds.Phone.LABEL;
+
+        /**
+         * The primary phone number.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PRIMARY_PHONE_NUMBER = CommonDataKinds.Phone.NUMBER;
     }
 
+
     /**
      * Constants for the aggregates table, which contains a record per group
      * of contact representing the same person.
@@ -163,7 +188,7 @@
 
         /**
          * The content:// style URI for this table joined with useful data from
-         * {@link Data} and {@link Presence}.
+         * {@link Data}.
          */
         public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI,
                 "aggregates_summary");
@@ -179,7 +204,7 @@
 
         /**
          * The content:// style URI for this table joined with useful data from
-         * {@link Data} and {@link Presence}, filtered to include only starred aggregates
+         * {@link Data}, filtered to include only starred aggregates
          * and the most frequently contacted aggregates.
          */
         public static final Uri CONTENT_SUMMARY_STREQUENT_URI = Uri.withAppendedPath(
@@ -196,7 +221,6 @@
 
         public static final Uri CONTENT_SUMMARY_GROUP_URI = Uri.withAppendedPath(
                 CONTENT_SUMMARY_URI, "group");
-
         /**
          * The MIME type of {@link #CONTENT_URI} providing a directory of
          * people.
@@ -291,7 +315,7 @@
 
     }
 
-    private interface ContactsColumns {
+    private interface RawContactsColumns {
         /**
          * A reference to the {@link Aggregates#_ID} that this data belongs to.
          * <P>Type: INTEGER</P>
@@ -299,7 +323,7 @@
         public static final String AGGREGATE_ID = "aggregate_id";
 
         /**
-         * Flag indicating that this {@link Contacts} entry and its children has
+         * Flag indicating that this {@link RawContacts} entry and its children has
          * been restricted to specific platform apps.
          * <P>Type: INTEGER (boolean)</P>
          *
@@ -315,14 +339,17 @@
     }
 
     /**
-     * Constants for the contacts table, which contains the base contact information.
+     * Constants for the raw_contacts table, which contains the base contact
+     * information per sync source. Sync adapters and contact management apps
+     * are the primary consumers of this API.
      */
-    public static final class Contacts implements BaseColumns, ContactsColumns, SyncColumns,
-            ContactOptionsColumns {
+    // TODO make final as soon as renaming is complete
+    public static /*final*/ class RawContacts implements BaseColumns, RawContactsColumns,
+            SyncColumns, ContactOptionsColumns {
         /**
          * This utility class cannot be instantiated
          */
-        private Contacts() {
+        private RawContacts() {
         }
 
         /**
@@ -387,6 +414,13 @@
         }
     }
 
+    /**
+     * TODO remove as soon as full renaming is complete.
+     */
+    @Deprecated
+    public static final class Contacts extends RawContacts {
+    }
+
     private interface DataColumns {
         /**
          * The package name to use when creating {@link Resources} objects for
@@ -511,11 +545,19 @@
      * back to specific {@link ContactsContract.Aggregates#_ID} entries.
      */
     private interface PresenceColumns {
+
         /**
-         * Reference to the {@link Aggregates#_ID} this presence references.
+         * The unique ID for a row.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String _ID = "presence_id";
+
+        /**
+         * Reference to the {@link android.provider.ContactsContract.Contacts#_ID} this presence
+         * references.
          * <P>Type: INTEGER</P>
          */
-        public static final String AGGREGATE_ID = "aggregate_id";
+        public static final String CONTACT_ID = "contact_id";
 
         /**
          * Reference to the {@link Data#_ID} entry that owns this presence.
@@ -545,8 +587,7 @@
         public static final String IM_ACCOUNT = "im_account";
     }
 
-    public static final class Presence implements BaseColumns, PresenceColumns,
-            Im.CommonPresenceColumns {
+    public static final class Presence implements PresenceColumns, Im.CommonPresenceColumns {
         /**
          * This utility class cannot be instantiated
          */
@@ -891,7 +932,7 @@
              * <p>
              * Type: TEXT
              */
-            public static final String NEIGHBOHOOD = "data8";
+            public static final String NEIGHBORHOOD = "data8";
 
             /**
              * Can be city, village, town, borough, etc. This is the postal town
@@ -919,7 +960,7 @@
             public static final String REGION = "data11";
 
             /**
-             * StructuredPostal code. Usually country-wide, but sometimes specific to the
+             * Postal code. Usually country-wide, but sometimes specific to the
              * city (e.g. "2" in "Dublin 2, Ireland" addresses).
              * <p>
              * Type: TEXT
@@ -1118,6 +1159,20 @@
         public static final String TITLE_RES = "title_res";
 
         /**
+         * Notes about the group.
+         * <p>
+         * Type: TEXT
+         */
+        public static final String NOTES = "notes";
+
+        /**
+         * The ID of this group if it is a System Group, i.e. a group that has a special meaning
+         * to the sync adapter, null otherwise.
+         * <P>Type: TEXT</P>
+         */
+        public static final String SYSTEM_ID = "system_id";
+
+        /**
          * The total number of {@link Aggregates} that have
          * {@link GroupMembership} in this group. Read-only value that is only
          * present when querying {@link Groups#CONTENT_SUMMARY_URI}.
@@ -1162,7 +1217,7 @@
 
         /**
          * The content:// style URI for this table joined with details data from
-         * {@link Data} and {@link Presence}.
+         * {@link Data}.
          */
         public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI,
                 "groups_summary");
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 42ba149..0c2b65e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2991,6 +2991,13 @@
         public static final String VENDING_TOS_URL = "vending_tos_url";
 
         /**
+         * URL to navigate to in browser (not Market) when the terms of service
+         * for Vending Machine could not be accessed due to bad network
+         * connection.
+         */
+        public static final String VENDING_TOS_MISSING_URL = "vending_tos_missing_url";
+
+        /**
          * Whether to use sierraqa instead of sierra tokens for the purchase flow in
          * Vending Machine.
          *
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 722a7cc..fb436e5 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -54,7 +54,6 @@
     private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
     private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
 
-    private static final String A2DP_SINK_ADDRESS = "a2dp_sink_address";
     private static final String BLUETOOTH_ENABLED = "bluetooth_enabled";
 
     private static final int MESSAGE_CONNECT_TO = 1;
@@ -238,7 +237,7 @@
                     }
             }
         }
-        mAudioManager.setParameter(BLUETOOTH_ENABLED, "true");
+        mAudioManager.setParameters(BLUETOOTH_ENABLED+"=true");
     }
 
     private synchronized void onBluetoothDisable() {
@@ -262,8 +261,8 @@
             }
             mAudioDevices.clear();
         }
-        mAudioManager.setBluetoothA2dpOn(false);
-        mAudioManager.setParameter(BLUETOOTH_ENABLED, "false");
+
+        mAudioManager.setParameters(BLUETOOTH_ENABLED+"=false");
     }
 
     public synchronized int connectSink(String address) {
@@ -403,8 +402,7 @@
                    Intent intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
                    mContext.sendBroadcast(intent);
                 }
-                if (--mSinkCount == 0)
-                    mAudioManager.setBluetoothA2dpOn(false);
+                mSinkCount--;
             } else if (state == BluetoothA2dp.STATE_CONNECTED) {
                 mSinkCount ++;
             }
@@ -417,11 +415,6 @@
             mContext.sendBroadcast(intent, BLUETOOTH_PERM);
 
             if (DBG) log("A2DP state : address: " + address + " State:" + prevState + "->" + state);
-
-            if (state == BluetoothA2dp.STATE_CONNECTED) {
-                mAudioManager.setParameter(A2DP_SINK_ADDRESS, address);
-                mAudioManager.setBluetoothA2dpOn(true);
-            }
         }
     }
 
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java
index b780f41..afe4757 100644
--- a/core/java/android/server/BluetoothDeviceService.java
+++ b/core/java/android/server/BluetoothDeviceService.java
@@ -286,6 +286,7 @@
                     SystemService.start("hsag");
                     SystemService.start("hfag");
                     SystemService.start("opush");
+                    SystemService.start("pbap");
                 }
                 break;
             case MESSAGE_FINISH_DISABLE:
diff --git a/core/java/android/server/search/SearchDialogWrapper.java b/core/java/android/server/search/SearchDialogWrapper.java
index d3ef5de..b8a9875 100644
--- a/core/java/android/server/search/SearchDialogWrapper.java
+++ b/core/java/android/server/search/SearchDialogWrapper.java
@@ -190,6 +190,9 @@
         msgData.putBundle(KEY_APP_SEARCH_DATA, appSearchData);
         msgData.putInt(KEY_IDENT, ident);
         mSearchUiThread.sendMessage(msg);
+        // be a little more eager in setting this so isVisible will return the correct value if
+        // called immediately after startSearch
+        mVisible = true;
     }
 
     /**
@@ -199,6 +202,9 @@
     public void stopSearch() {
         if (DBG) debug("stopSearch()");
         mSearchUiThread.sendEmptyMessage(MSG_STOP_SEARCH);
+        // be a little more eager in setting this so isVisible will return the correct value if
+        // called immediately after stopSearch
+        mVisible = false;
     }
 
     /**
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index bb6b4b0..8f8d976 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -921,8 +921,10 @@
                 mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1] = loc.getISO3Language();
                 mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country();
                 mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = loc.getVariant();
-
-                result = mITts.setLanguage(mPackageName,
+                // the language is not set here, instead it is cached so it will be associated
+                // with all upcoming utterances. But we still need to report the language support,
+                // which is achieved by calling isLanguageAvailable()
+                result = mITts.isLanguageAvailable(
                         mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1],
                         mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1],
                         mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] );
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 3d10f17..524f941 100644
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -284,6 +284,12 @@
      */
     public static java.text.DateFormat getDateFormatForSetting(Context context,
                                                                String value) {
+        String format = getDateFormatStringForSetting(context, value);
+
+        return new java.text.SimpleDateFormat(format);
+    }
+
+    private static String getDateFormatStringForSetting(Context context, String value) {
         if (value != null) {
             int month = value.indexOf('M');
             int day = value.indexOf('d');
@@ -291,7 +297,7 @@
 
             if (month >= 0 && day >= 0 && year >= 0) {
                 String template = context.getString(R.string.numeric_date_template);
-                if (year < month) {
+                if (year < month && year < day) {
                     if (month < day) {
                         value = String.format(template, "yyyy", "MM", "dd");
                     } else {
@@ -311,7 +317,7 @@
                     }
                 }
 
-                return new java.text.SimpleDateFormat(value);
+                return value;
             }
         }
 
@@ -321,7 +327,7 @@
          * so that we get a four-digit year instead a two-digit year.
          */
         value = context.getString(R.string.numeric_date_format);
-        return new java.text.SimpleDateFormat(value);
+        return value;
     }
     
     /**
@@ -347,7 +353,11 @@
     /**
      * Gets the current date format stored as a char array. The array will contain
      * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order    
-     * preferred by the user.
+     * specified by the user's format preference.  Note that this order is
+     * only appropriate for all-numeric dates; spelled-out (MEDIUM and LONG)
+     * dates will generally contain other punctuation, spaces, or words,
+     * not just the day, month, and year, and not necessarily in the same
+     * order returned here.
      */    
     public static final char[] getDateFormatOrder(Context context) {
         char[] order = new char[] {DATE, MONTH, YEAR};
@@ -380,22 +390,10 @@
     }
     
     private static String getDateFormatString(Context context) {
-        java.text.DateFormat df;
-        df = java.text.DateFormat.getDateInstance(java.text.DateFormat.SHORT);
-        if (df instanceof SimpleDateFormat) {
-            return ((SimpleDateFormat) df).toPattern();
-        }
-
         String value = Settings.System.getString(context.getContentResolver(),
                 Settings.System.DATE_FORMAT);
-        if (value == null || value.length() < 6) {
-            /*
-             * No need to localize -- this is an emergency fallback in case
-             * the setting is missing, but it should always be set.
-             */
-            value = "MM-dd-yyyy";
-        }
-        return value;
+
+        return getDateFormatStringForSetting(context, value);
     }
 
     /**
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 29c0c76..911a23c 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -43,7 +43,7 @@
      */
     public ImageSpan(Bitmap b, int verticalAlignment) {
         super(verticalAlignment);
-        mDrawable = new BitmapDrawable(b);
+        mDrawable = new BitmapDrawable(mContext.getResources(), b);
         int width = mDrawable.getIntrinsicWidth();
         int height = mDrawable.getIntrinsicHeight();
         mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0); 
@@ -117,7 +117,7 @@
                 InputStream is = mContext.getContentResolver().openInputStream(
                         mContentUri);
                 bitmap = BitmapFactory.decodeStream(is);
-                drawable = new BitmapDrawable(bitmap);
+                drawable = new BitmapDrawable(mContext.getResources(), bitmap);
                 drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
                         drawable.getIntrinsicHeight());
                 is.close();
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 061f98a..dd5a440 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -80,6 +80,11 @@
      */
     public float density;
     /**
+     * The screen density expressed as dots-per-inch.  May be either
+     * {@link #DENSITY_LOW}, {@link #DENSITY_MEDIUM}, or {@link #DENSITY_HIGH}.
+     */
+    public int densityDpi;
+    /**
      * A scaling factor for fonts displayed on the display.  This is the same
      * as {@link #density}, except that it may be adjusted in smaller
      * increments at runtime based on a user preference for the font size.
@@ -101,6 +106,7 @@
         widthPixels = o.widthPixels;
         heightPixels = o.heightPixels;
         density = o.density;
+        densityDpi = o.densityDpi;
         scaledDensity = o.scaledDensity;
         xdpi = o.xdpi;
         ydpi = o.ydpi;
@@ -110,6 +116,7 @@
         widthPixels = 0;
         heightPixels = 0;
         density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
+        densityDpi = DENSITY_DEVICE;
         scaledDensity = density;
         xdpi = DENSITY_DEVICE;
         ydpi = DENSITY_DEVICE;
@@ -186,9 +193,11 @@
                 heightPixels = defaultHeight;
             }
         }
+        
         if (compatibilityInfo.isScalingRequired()) {
             float invertedRatio = compatibilityInfo.applicationInvertedScale;
             density *= invertedRatio;
+            densityDpi = (int)((density*DisplayMetrics.DENSITY_DEFAULT)+.5f);
             scaledDensity *= invertedRatio;
             xdpi *= invertedRatio;
             ydpi *= invertedRatio;
diff --git a/core/java/android/util/Pair.java b/core/java/android/util/Pair.java
new file mode 100644
index 0000000..bf25306
--- /dev/null
+++ b/core/java/android/util/Pair.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 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.util;
+
+/**
+ * Container to ease passing around a tuple of two objects. This object provides a sensible
+ * implementation of equals(), returning true if equals() is true on each of the contained
+ * objects.
+ */
+public class Pair<F, S> {
+    public final F first;
+    public final S second;
+
+    /**
+     * Constructor for a Pair. If either are null then equals() and hashCode() will throw
+     * a NullPointerException.
+     * @param first the first object in the Pair
+     * @param second the second object in the pair
+     */
+    public Pair(F first, S second) {
+        this.first = first;
+        this.second = second;
+    }
+
+    /**
+     * Checks the two objects for equality by delegating to their respective equals() methods.
+     * @param o the Pair to which this one is to be checked for equality
+     * @return true if the underlying objects of the Pair are both considered equals()
+     */
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (!(o instanceof Pair)) return false;
+        final Pair<F, S> other;
+        try {
+            other = (Pair<F, S>) o;
+        } catch (ClassCastException e) {
+            return false;
+        }
+        return first.equals(other.first) && second.equals(other.second);
+    }
+
+    /**
+     * Compute a hash code using the hash codes of the underlying objects
+     * @return a hashcode of the Pair
+     */
+    public int hashCode() {
+        int result = 17;
+        result = 31 * result + first.hashCode();
+        result = 31 * result + second.hashCode();
+        return result;
+    }
+
+    /**
+     * Convenience method for creating an appropriately typed pair.
+     * @param a the first object in the Pair
+     * @param b the second object in the pair
+     * @return a Pair that is templatized with the types of a and b
+     */
+    public static <A, B> Pair <A, B> create(A a, B b) {
+        return new Pair<A, B>(a, b);
+    }
+}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5551f64..b055d51 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -94,6 +94,7 @@
         outMetrics.widthPixels  = getWidth();
         outMetrics.heightPixels = getHeight();
         outMetrics.density      = mDensity;
+        outMetrics.densityDpi   = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
         outMetrics.scaledDensity= outMetrics.density;
         outMetrics.xdpi         = mDpiX;
         outMetrics.ydpi         = mDpiY;
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index 841066c..f936f65 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -24,9 +24,18 @@
 
     private HapticFeedbackConstants() {}
 
+    /**
+     * The user has performed a long press on an object that is resulting
+     * in an action being performed.
+     */
     public static final int LONG_PRESS = 0;
     
     /**
+     * The user has pressed on a virtual on-screen key.
+     */
+    public static final int VIRTUAL_KEY = 1;
+    
+    /**
      * Flag for {@link View#performHapticFeedback(int, int)
      * View.performHapticFeedback(int, int)}: Ignore the setting in the
      * view for whether to perform haptic feedback, do it always.
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 6349288..f9b16fc 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -258,6 +258,25 @@
     public static final int FLAG_EDITOR_ACTION = 0x10;
     
     /**
+     * When associated with up key events, this indicates that the key press
+     * has been canceled.  Typically this is used with virtual touch screen
+     * keys, where the user can slide from the virtual key area on to the
+     * display: in that case, the application will receive a canceled up
+     * event and should not perform the action normally associated with the
+     * key.  Note that for this to work, the application can not perform an
+     * action for a key until it receives an up or the long press timeout has
+     * expired. 
+     */
+    public static final int FLAG_CANCELED = 0x20;
+    
+    /**
+     * This key event was generated by a virtual (on-screen) hard key area.
+     * Typically this is an area of the touchscreen, outside of the regular
+     * display, dedicated to "hardware" buttons.
+     */
+    public static final int FLAG_VIRTUAL_HARD_KEY = 0x40;
+    
+    /**
      * Returns the maximum keycode.
      */
     public static int getMaxKeyCode() {
@@ -694,6 +713,14 @@
     }
 
     /**
+     * For {@link #ACTION_UP} events, indicates that the event has been
+     * canceled as per {@link #FLAG_CANCELED}.
+     */
+    public final boolean isCanceled() {
+        return (mFlags&FLAG_CANCELED) != 0;
+    }
+    
+    /**
      * Retrieve the key code of the key event.  This is the physical key that
      * was pressed, <em>not</em> the Unicode character.
      * 
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 52f1a97..89b721d 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -288,9 +288,10 @@
         ev.mEventTimeNano = eventTimeNano;
         ev.mAction = action;
         ev.mMetaState = metaState;
+        ev.mRawX = inData[SAMPLE_X];
+        ev.mRawY = inData[SAMPLE_Y];
         ev.mXPrecision = xPrecision;
         ev.mYPrecision = yPrecision;
-        
         ev.mNumPointers = pointers;
         ev.mNumSamples = 1;
         
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index e6bbf9f5..9178131 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.content.res.CompatibilityInfo.Translator;
 import android.graphics.*;
 import android.os.Parcelable;
 import android.os.Parcel;
@@ -135,8 +136,12 @@
     private Canvas mCanvas;
 
     // The display metrics used to provide the pseudo canvas size for applications
-    // running in compatibility mode. This is set to null for regular mode.
-    private DisplayMetrics mDisplayMetrics;
+    // running in compatibility mode. This is set to null for non compatibility mode.
+    private DisplayMetrics mCompatibleDisplayMetrics;
+
+    // A matrix to scale the matrix set by application. This is set to null for
+    // non compatibility mode.
+    private Matrix mCompatibleMatrix;
 
     /**
      * Exception thrown when a surface couldn't be created or resized
@@ -174,23 +179,70 @@
      * {@hide}
      */
     public Surface() {
-        mCanvas = new Canvas() {
-            @Override
-            public int getWidth() {
-                return mDisplayMetrics == null ? super.getWidth() : mDisplayMetrics.widthPixels;
-            }
-            @Override
-            public int getHeight() {
-                return mDisplayMetrics == null ? super.getHeight() : mDisplayMetrics.heightPixels;
-            }
-        };
+        mCanvas = new CompatibleCanvas();
     }
 
     /**
+     * A Canvas class that can handle the compatibility mode. This does two things differently.
+     * <ul>
+     *  <li> Returns the width and height of the target metrics, rather than native.
+     *  For example, the canvas returns 320x480 even if an app is running in WVGA high density.
+     *  <li> Scales the matrix in setMatrix by the application scale, except if the matrix looks
+     *  like obtained from getMatrix. This is a hack to handle the case that an application
+     *  uses getMatrix to keep the original matrix, set matrix of its own, then set the original
+     *  matrix back. There is no perfect solution that works for all cases, and there are a lot of
+     *  cases that this model dose not work, but we hope this works for many apps.
+     * </ul>
+     */
+    private class CompatibleCanvas extends Canvas {
+        // A temp matrix to remember what an application obtained via {@link getMatrix}
+        private Matrix mOrigMatrix = null;
+
+        @Override
+        public int getWidth() {
+            return mCompatibleDisplayMetrics == null ?
+                    super.getWidth() : mCompatibleDisplayMetrics.widthPixels;
+        }
+
+        @Override
+        public int getHeight() {
+            return mCompatibleDisplayMetrics == null ?
+                    super.getHeight() : mCompatibleDisplayMetrics.heightPixels;
+        }
+
+        @Override
+        public void setMatrix(Matrix matrix) {
+            if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
+                // don't scale the matrix if it's not compatibility mode, or
+                // the matrix was obtained from getMatrix.
+                super.setMatrix(matrix);
+            } else {
+                Matrix m = new Matrix(mCompatibleMatrix);
+                m.preConcat(matrix);
+                super.setMatrix(m);
+            }
+        }
+
+        @Override
+        public void getMatrix(Matrix m) {
+            super.getMatrix(m);
+            if (mOrigMatrix == null) {
+                mOrigMatrix = new Matrix(); 
+            }
+            mOrigMatrix.set(m);
+        }
+    };
+
+    /**
      * Sets the display metrics used to provide canva's width/height in comaptibility mode.
      */
-    void setCompatibleDisplayMetrics(DisplayMetrics metrics) {
-        mDisplayMetrics = metrics;
+    void setCompatibleDisplayMetrics(DisplayMetrics metrics, Translator translator) {
+        mCompatibleDisplayMetrics = metrics;
+        if (translator != null) {
+            float appScale = translator.applicationScale;
+            mCompatibleMatrix = new Matrix();
+            mCompatibleMatrix.setScale(appScale, appScale);
+        }
     }
     
     /**
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 277b347..4546572 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -141,7 +141,7 @@
     int mType = -1;
     final Rect mSurfaceFrame = new Rect();
     private Translator mTranslator;
-
+    
     public SurfaceView(Context context) {
         super(context);
         setWillNotDraw(true);
@@ -254,23 +254,6 @@
     }
 
     @Override
-    public boolean dispatchTouchEvent(MotionEvent event) {
-        // SurfaceView uses pre-scaled size unless fixed size is requested. This hook
-        // scales the event back to the pre-scaled coordinates for such surface.
-        if (mScaled) {
-            MotionEvent scaledBack = MotionEvent.obtain(event);
-            mTranslator.translateEventInScreenToAppWindow(event);
-            try {
-                return super.dispatchTouchEvent(scaledBack);
-            } finally {
-                scaledBack.recycle();
-            }
-        } else {
-            return super.dispatchTouchEvent(event);
-        }
-    }
-
-    @Override
     protected void dispatchDraw(Canvas canvas) {
         // if SKIP_DRAW is cleared, draw() has already punched a hole
         if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
@@ -292,8 +275,6 @@
         mWindowType = type;
     }
 
-    boolean mScaled = false;
-    
     private void updateWindow(boolean force) {
         if (!mHaveFrame) {
             return;
@@ -301,11 +282,9 @@
         ViewRoot viewRoot = (ViewRoot) getRootView().getParent();
         mTranslator = viewRoot.mTranslator;
 
-        float appScale = mTranslator == null ? 1.0f : mTranslator.applicationScale;
-        
         Resources res = getContext().getResources();
         if (mTranslator != null || !res.getCompatibilityInfo().supportsScreen()) {
-            mSurface.setCompatibleDisplayMetrics(res.getDisplayMetrics());
+            mSurface.setCompatibleDisplayMetrics(res.getDisplayMetrics(), mTranslator);
         }
         
         int myWidth = mRequestedWidth;
@@ -313,16 +292,6 @@
         int myHeight = mRequestedHeight;
         if (myHeight <= 0) myHeight = getHeight();
 
-        // Use original size if the app specified the size of the view,
-        // and let the flinger to scale up.
-        if (mRequestedWidth <= 0 && mTranslator != null) {
-            myWidth = (int) (myWidth * appScale + 0.5f);
-            myHeight = (int) (myHeight * appScale + 0.5f);
-            mScaled = true;
-        } else {
-            mScaled = false;
-        }
-
         getLocationInWindow(mLocation);
         final boolean creating = mWindow == null;
         final boolean formatChanged = mFormat != mRequestedFormat;
@@ -395,10 +364,17 @@
 
                 if (localLOGV) Log.i(TAG, "New surface: " + mSurface
                         + ", vis=" + visible + ", frame=" + mWinFrame);
+                
                 mSurfaceFrame.left = 0;
                 mSurfaceFrame.top = 0;
-                mSurfaceFrame.right = mWinFrame.width();
-                mSurfaceFrame.bottom = mWinFrame.height();
+                if (mTranslator == null) {
+                    mSurfaceFrame.right = mWinFrame.width();
+                    mSurfaceFrame.bottom = mWinFrame.height();
+                } else {
+                    float appInvertedScale = mTranslator.applicationInvertedScale;
+                    mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f);
+                    mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f);
+                }
                 mSurfaceLock.unlock();
 
                 try {
@@ -642,10 +618,6 @@
             if (localLOGV) Log.i(TAG, "Returned canvas: " + c);
             if (c != null) {
                 mLastLockTime = SystemClock.uptimeMillis();
-                if (mScaled) {
-                    mSaveCount = c.save();
-                    mTranslator.translateCanvas(c);
-                }
                 return c;
             }
             
@@ -668,9 +640,6 @@
         }
 
         public void unlockCanvasAndPost(Canvas canvas) {
-            if (mScaled) {
-                canvas.restoreToCount(mSaveCount);
-            }
             mSurface.unlockCanvasAndPost(canvas);
             mSurfaceLock.unlock();
         }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ff8868b..7ed2712 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -46,6 +46,7 @@
 import android.os.SystemProperties;
 import android.util.AttributeSet;
 import android.util.Config;
+import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Pool;
@@ -5976,6 +5977,7 @@
 
                 try {
                     bitmap = Bitmap.createBitmap(width, height, quality);
+                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
                     if (autoScale) {
                         mDrawingCache = new SoftReference<Bitmap>(bitmap);
                     } else {
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 242690b..884950f 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -191,7 +191,7 @@
      */
     AudioManager mAudioManager;
 
-    private final float mDensity;
+    private final int mDensity;
 
     public ViewRoot(Context context) {
         super();
@@ -236,7 +236,7 @@
         mAdded = false;
         mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, this);
         mViewConfiguration = ViewConfiguration.get(context);
-        mDensity = context.getResources().getDisplayMetrics().density;
+        mDensity = context.getResources().getDisplayMetrics().densityDpi;
     }
 
     @Override
@@ -396,10 +396,11 @@
                 attrs = mWindowAttributes;
                 Resources resources = mView.getContext().getResources();
                 CompatibilityInfo compatibilityInfo = resources.getCompatibilityInfo();
-                mTranslator = compatibilityInfo.getTranslator(attrs);
+                mTranslator = compatibilityInfo.getTranslator();
 
                 if (mTranslator != null || !compatibilityInfo.supportsScreen()) {
-                    mSurface.setCompatibleDisplayMetrics(resources.getDisplayMetrics());
+                    mSurface.setCompatibleDisplayMetrics(resources.getDisplayMetrics(),
+                            mTranslator);
                 }
 
                 boolean restore = false;
@@ -1276,7 +1277,7 @@
             }
 
             // TODO: Do this in native
-            canvas.setDensityScale(mDensity);
+            canvas.setDensity(mDensity);
         } catch (Surface.OutOfResourcesException e) {
             Log.e("ViewRoot", "OutOfResourcesException locking surface", e);
             // TODO: we should ask the window manager to do something!
@@ -1664,7 +1665,9 @@
                     if(Config.LOGV) {
                         captureMotionLog("captureDispatchPointer", event);
                     }
-                    event.offsetLocation(0, mCurScrollY);
+                    if (mCurScrollY != 0) {
+                        event.offsetLocation(0, mCurScrollY);
+                    }
                     if (MEASURE_LATENCY) {
                         lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
                     }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 1371932..f4e9900 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -533,14 +533,15 @@
      * @param win The window that currently has focus.  This is where the key
      *            event will normally go.
      * @param code Key code.
-     * @param metaKeys TODO
+     * @param metaKeys bit mask of meta keys that are held.
      * @param down Is this a key press (true) or release (false)?
      * @param repeatCount Number of times a key down has repeated.
+     * @param flags event's flags.
      * @return Returns true if the policy consumed the event and it should
      * not be further dispatched.
      */
     public boolean interceptKeyTi(WindowState win, int code,
-                               int metaKeys, boolean down, int repeatCount);
+                               int metaKeys, boolean down, int repeatCount, int flags);
 
     /**
      * Called when layout of the windows is about to start.
@@ -792,6 +793,13 @@
     public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always);
     
     /**
+     * A special function that is called from the very low-level input queue
+     * to provide feedback to the user.  Currently only called for virtual
+     * keys.
+     */
+    public void keyFeedbackFromInput(KeyEvent event);
+    
+    /**
      * Called when we have stopped keeping the screen on because a window
      * requesting this is no longer visible.
      */
diff --git a/core/java/android/webkit/HttpDateTime.java b/core/java/android/webkit/HttpDateTime.java
index 48b2081f..00b2731 100644
--- a/core/java/android/webkit/HttpDateTime.java
+++ b/core/java/android/webkit/HttpDateTime.java
@@ -23,7 +23,8 @@
 import java.util.regex.Pattern;
 
 
-class HttpDateTime {
+/** {@hide} */
+public final class HttpDateTime {
 
     /*
      * Regular expression for parsing HTTP-date.
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index 4fe4036..3da5a3c 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -31,7 +31,6 @@
 import android.security.CertTool;
 import android.util.Log;
 import android.webkit.CacheManager.CacheResult;
-import android.widget.Toast;
 
 import com.android.internal.R;
 
@@ -997,8 +996,6 @@
                 mDataBuilder.releaseChunk(c);
             }
             CertTool.getInstance().addCertificate(cert, mContext);
-            Toast.makeText(mContext, R.string.certificateSaved,
-                    Toast.LENGTH_SHORT).show();
             mBrowserFrame.stopLoading();
             return;
         }
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 8f3d55f..b56f167 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -181,6 +181,7 @@
     private boolean         mDatabaseEnabled = false;
     private String          mAppCachePath = "";
     private boolean         mAppCacheEnabled = false;
+    private long            mAppCacheMaxSize = Long.MAX_VALUE;
     private boolean         mDomStorageEnabled = false;
 
     // Class to handle messages before WebCore is ready.
@@ -996,6 +997,19 @@
     }
 
     /**
+     * Set the maximum size for the Application Caches content.
+     * @param appCacheMaxSize the maximum size in bytes.
+     *
+     * @hide pending api council approval
+     */
+    public synchronized void setAppCacheMaxSize(long appCacheMaxSize) {
+        if (appCacheMaxSize != mAppCacheMaxSize) {
+            mAppCacheMaxSize = appCacheMaxSize;
+            postSync();
+        }
+    }
+
+    /**
      * Set whether the database storage API is enabled.
      * @param flag boolean True if the WebView should use the database storage
      *     API.
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index 7522b5a5..1a60dba 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -51,8 +51,9 @@
     // Global instance of a WebStorage
     private static WebStorage sWebStorage;
 
-    // We keep a copy of the origins, quotas and usages
-    // that we protect via a lock and update in syncValues()
+    // We keep the origins, quotas and usages as member values
+    // that we protect via a lock and update in syncValues().
+    // This is needed to transfer this data across threads.
     private static Lock mLock = new ReentrantLock();
     private static Condition mCacheUpdated = mLock.newCondition();
 
@@ -104,18 +105,15 @@
                             Origin website = (Origin) msg.obj;
                             nativeSetQuotaForOrigin(website.getOrigin(),
                                                     website.getQuota());
-                            syncValues();
                             } break;
 
                         case DELETE_ORIGIN: {
                             Origin website = (Origin) msg.obj;
                             nativeDeleteOrigin(website.getOrigin());
-                            syncValues();
                             } break;
 
                         case DELETE_ALL:
                             nativeDeleteAllData();
-                            syncValues();
                             break;
 
                         case UPDATE:
@@ -204,7 +202,6 @@
         if (origin != null) {
             if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
                 nativeSetQuotaForOrigin(origin, quota);
-                syncValues();
             } else {
                 postMessage(Message.obtain(null, SET_QUOTA_ORIGIN,
                     new Origin(origin, quota)));
@@ -220,7 +217,6 @@
         if (origin != null) {
             if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
                 nativeDeleteOrigin(origin);
-                syncValues();
             } else {
                 postMessage(Message.obtain(null, DELETE_ORIGIN,
                     new Origin(origin)));
@@ -235,7 +231,6 @@
     public void deleteAllData() {
         if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
             nativeDeleteAllData();
-            syncValues();
         } else {
             postMessage(Message.obtain(null, DELETE_ALL));
         }
@@ -276,7 +271,7 @@
 
     /**
      * Run on the webcore thread
-     * sync the local cached values with the real ones
+     * set the local values with the current ones
      */
     private void syncValues() {
         mLock.lock();
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index da1443c..7bc154b 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -31,6 +31,7 @@
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.method.MovementMethod;
+import android.text.method.Touch;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.KeyCharacterMap;
@@ -71,6 +72,15 @@
     // need to send down the DOM events.
     private String          mPreChange;
     private Drawable        mBackground;
+    // Variables for keeping track of the touch down, to send to the WebView
+    // when a drag starts
+    private float           mDragStartX;
+    private float           mDragStartY;
+    private long            mDragStartTime;
+    private boolean         mDragSent;
+    // True if the most recent drag event has caused either the TextView to
+    // scroll or the web page to scroll.  Gets reset after a touch down.
+    private boolean         mScrolled;
     // Array to store the final character added in onTextChanged, so that its
     // KeyEvents may be determined.
     private char[]          mCharacter = new char[1];
@@ -366,6 +376,66 @@
     }
 
     @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        switch (event.getAction()) {
+        case MotionEvent.ACTION_DOWN:
+            super.onTouchEvent(event);
+            // This event may be the start of a drag, so store it to pass to the
+            // WebView if it is.
+            mDragStartX = event.getX();
+            mDragStartY = event.getY();
+            mDragStartTime = event.getEventTime();
+            mDragSent = false;
+            mScrolled = false;
+            break;
+        case MotionEvent.ACTION_MOVE:
+            Spannable buffer = getText();
+            int initialScrollX = Touch.getInitialScrollX(this, buffer);
+            int initialScrollY = Touch.getInitialScrollY(this, buffer);
+            super.onTouchEvent(event);
+            if (mScrollX != initialScrollX
+                    || mScrollY != initialScrollY) {
+                if (mWebView != null) {
+                    mWebView.scrollFocusedTextInput(mScrollX, mScrollY);
+                }
+                mScrolled = true;
+                return true;
+            }
+            if (mWebView != null) {
+                // Only want to set the initial state once.
+                if (!mDragSent) {
+                    mWebView.initiateTextFieldDrag(mDragStartX, mDragStartY,
+                            mDragStartTime);
+                    mDragSent = true;
+                }
+                boolean scrolled = mWebView.textFieldDrag(event);
+                if (scrolled) {
+                    mScrolled = true;
+                    cancelLongPress();
+                    return true;
+                }
+            }
+            return false;
+        case MotionEvent.ACTION_UP:
+        case MotionEvent.ACTION_CANCEL:
+            if (!mScrolled) {
+                // If the page scrolled, or the TextView scrolled, we do not
+                // want to change the selection, and the long press has already
+                // been canceled, so there is no need to call into super.
+                super.onTouchEvent(event);
+            }
+            // Necessary for the WebView to reset its state
+            if (mWebView != null && mDragSent) {
+                mWebView.onTouchEvent(event);
+            }
+            break;
+        default:
+            break;
+        }
+        return true;
+    }
+
+    @Override
     public boolean onTrackballEvent(MotionEvent event) {
         if (isPopupShowing()) {
             return super.onTrackballEvent(event);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c1ba690..19df87f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -379,6 +379,10 @@
     // take control of touch events unless it says no for touch down event.
     private boolean mPreventDrag;
 
+    // To keep track of whether the current drag was initiated by a WebTextView,
+    // so that we know not to hide the cursor
+    boolean mDragFromTextInput;
+
     // Whether or not to draw the cursor ring.
     private boolean mDrawCursorRing = true;
 
@@ -531,6 +535,8 @@
     private float mZoomScale;
     private float mInvInitialZoomScale;
     private float mInvFinalZoomScale;
+    private int mInitialScrollX;
+    private int mInitialScrollY;
     private long mZoomStart;
     private static final int ZOOM_ANIMATION_LENGTH = 500;
 
@@ -2558,24 +2564,15 @@
                 // set mZoomScale to be 0 as we have done animation
                 mZoomScale = 0;
             }
-            float scale = (mActualScale - zoomScale) * mInvActualScale;
-            float tx = scale * (mZoomCenterX + mScrollX);
-            float ty = scale * (mZoomCenterY + mScrollY);
-
-            // this block pins the translate to "legal" bounds. This makes the
-            // animation a bit non-obvious, but it means we won't pop when the
-            // "real" zoom takes effect
-            if (true) {
-               // canvas.translate(mScrollX, mScrollY);
-                tx -= mScrollX;
-                ty -= mScrollY;
-                tx = -pinLoc(-Math.round(tx), getViewWidth(), Math
-                        .round(mContentWidth * zoomScale));
-                ty = -pinLoc(-Math.round(ty), getViewHeight(), Math
-                        .round(mContentHeight * zoomScale));
-                tx += mScrollX;
-                ty += mScrollY;
-            }
+            float scale = zoomScale * mInvInitialZoomScale;
+            int tx = Math.round(scale * (mInitialScrollX + mZoomCenterX)
+                    - mZoomCenterX);
+            tx = -pinLoc(tx, getViewWidth(), Math.round(mContentWidth
+                    * zoomScale)) + mScrollX;
+            int ty = Math.round(scale * (mInitialScrollY + mZoomCenterY)
+                    - mZoomCenterY);
+            ty = -pinLoc(ty, getViewHeight(), Math.round(mContentHeight
+                    * zoomScale)) + mScrollY;
             canvas.translate(tx, ty);
             canvas.scale(zoomScale, zoomScale);
         } else {
@@ -3830,7 +3827,9 @@
 
                     mTouchMode = TOUCH_DRAG_MODE;
                     WebViewCore.pauseUpdate(mWebViewCore);
-                    nativeHideCursor();
+                    if (!mDragFromTextInput) {
+                        nativeHideCursor();
+                    }
                     // remove the zoom anchor if there is any
                     if (mZoomScale != 0) {
                         mWebViewCore
@@ -4350,6 +4349,8 @@
 
     private boolean zoomWithPreview(float scale) {
         float oldScale = mActualScale;
+        mInitialScrollX = mScrollX;
+        mInitialScrollY = mScrollY;
 
         // snap to DEFAULT_SCALE if it is close
         if (scale > (mDefaultScale - 0.05) && scale < (mDefaultScale + 0.05)) {
@@ -4494,6 +4495,54 @@
         nativeSelectBestAt(rect);
     }
 
+    /**
+     * Scroll the focused text field/area to match the WebTextView
+     * @param x New x position of the WebTextView in view coordinates
+     * @param y New y position of the WebTextView in view coordinates
+     */
+    /*package*/ void scrollFocusedTextInput(int x, int y) {
+        if (!inEditingMode() || mWebViewCore == null) {
+            return;
+        }
+        mWebViewCore.sendMessage(EventHub.SCROLL_TEXT_INPUT, viewToContent(x),
+                viewToContent(y));
+    }
+
+    /**
+     * Set our starting point and time for a drag from the WebTextView.
+     */
+    /*package*/ void initiateTextFieldDrag(float x, float y, long eventTime) {
+        if (!inEditingMode()) {
+            return;
+        }
+        mLastTouchX = x + (float) (mWebTextView.getLeft() - mScrollX);
+        mLastTouchY = y + (float) (mWebTextView.getTop() - mScrollY);
+        mLastTouchTime = eventTime;
+        if (!mScroller.isFinished()) {
+            mScroller.abortAnimation();
+            mPrivateHandler.removeMessages(RESUME_WEBCORE_UPDATE);
+        }
+        mSnapScrollMode = SNAP_NONE;
+        mVelocityTracker = VelocityTracker.obtain();
+        mTouchMode = TOUCH_DRAG_START_MODE;
+    }
+
+    /**
+     * Given a motion event from the WebTextView, set its location to our
+     * coordinates, and handle the event.
+     */
+    /*package*/ boolean textFieldDrag(MotionEvent event) {
+        if (!inEditingMode()) {
+            return false;
+        }
+        mDragFromTextInput = true;
+        event.offsetLocation((float) (mWebTextView.getLeft() - mScrollX),
+                (float) (mWebTextView.getTop() - mScrollY));
+        boolean result = onTouchEvent(event);
+        mDragFromTextInput = false;
+        return result;
+    }
+
     /*package*/ void shortPressOnTextField() {
         if (inEditingMode()) {
             View v = mWebTextView;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 99ceec2..4993fcf 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -591,6 +591,7 @@
     }
 
         static final String[] HandlerDebugString = {
+            "SCROLL_TEXT_INPUT", // = 99
             "LOAD_URL", // = 100;
             "STOP_LOADING", // = 101;
             "RELOAD", // = 102;
@@ -641,6 +642,7 @@
 
     class EventHub {
         // Message Ids
+        static final int SCROLL_TEXT_INPUT = 99;
         static final int LOAD_URL = 100;
         static final int STOP_LOADING = 101;
         static final int RELOAD = 102;
@@ -745,9 +747,10 @@
                 @Override
                 public void handleMessage(Message msg) {
                     if (DebugFlags.WEB_VIEW_CORE) {
-                        Log.v(LOGTAG, (msg.what < LOAD_URL || msg.what
+                        Log.v(LOGTAG, (msg.what < SCROLL_TEXT_INPUT || msg.what
                                 > FREE_MEMORY ? Integer.toString(msg.what)
-                                : HandlerDebugString[msg.what - LOAD_URL])
+                                : HandlerDebugString[msg.what
+                                        - SCROLL_TEXT_INPUT])
                                 + " arg1=" + msg.arg1 + " arg2=" + msg.arg2
                                 + " obj=" + msg.obj);
                     }
@@ -764,6 +767,10 @@
                             mNativeClass = 0;
                             break;
 
+                        case SCROLL_TEXT_INPUT:
+                            nativeScrollFocusedTextInput(msg.arg1, msg.arg2);
+                            break;
+
                         case LOAD_URL:
                             loadUrl((String) msg.obj);
                             break;
@@ -1797,6 +1804,11 @@
                 WebView.CLEAR_TEXT_ENTRY).sendToTarget();
     }
 
+    /**
+     * Scroll the focused textfield to (x, y) in document space
+     */
+    private native void nativeScrollFocusedTextInput(int x, int y);
+
     // these must be in document space (i.e. not scaled/zoomed).
     private native void nativeSetScrollOffset(int gen, int dx, int dy);
 
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 777beed..eea97dc 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1535,6 +1535,9 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
 
+        // Dismiss the popup in case onSaveInstanceState() was not invoked
+        dismissPopup();
+
         final ViewTreeObserver treeObserver = getViewTreeObserver();
         if (treeObserver != null) {
             treeObserver.removeOnTouchModeChangeListener(this);
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 09a547f..e613ec4 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -116,6 +116,8 @@
     private boolean mDropDownAlwaysVisible = false;
 
     private boolean mDropDownDismissedOnCompletion = true;
+    
+    private boolean mForceIgnoreOutsideTouch = false;
 
     private int mLastKeyCode = KeyEvent.KEYCODE_UNKNOWN;
     private boolean mOpenBefore;
@@ -205,11 +207,10 @@
      * Private hook into the on click event, dispatched from {@link PassThroughClickListener}
      */
     private void onClickImpl() {
-        // if drop down should always visible, bring it back in front of the soft
-        // keyboard when the user touches the text field
-        if (mDropDownAlwaysVisible
-                && mPopup.isShowing()
-                && mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED) {
+        // If the dropdown is showing, bring it back in front of the soft
+        // keyboard when the user touches the text field.
+        if (mPopup.isShowing() &&
+                mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED) {
             ensureImeVisible();
         }
     }
@@ -1129,6 +1130,8 @@
                 heightSpec = mDropDownHeight;
             }
 
+            mPopup.setOutsideTouchable(mForceIgnoreOutsideTouch ? false : !mDropDownAlwaysVisible);
+
             mPopup.update(getDropDownAnchorView(), mDropDownHorizontalOffset,
                     mDropDownVerticalOffset, widthSpec, heightSpec);
         } else {
@@ -1154,7 +1157,10 @@
 
             mPopup.setWindowLayoutMode(widthSpec, heightSpec);
             mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
-            mPopup.setOutsideTouchable(true);
+            
+            // use outside touchable to dismiss drop down when touching outside of it, so
+            // only set this if the dropdown is not always visible
+            mPopup.setOutsideTouchable(mForceIgnoreOutsideTouch ? false : !mDropDownAlwaysVisible);
             mPopup.setTouchInterceptor(new PopupTouchIntercepter());
             mPopup.showAsDropDown(getDropDownAnchorView(),
                     mDropDownHorizontalOffset, mDropDownVerticalOffset);
@@ -1163,6 +1169,17 @@
             post(mHideSelector);
         }
     }
+    
+    /**
+     * Forces outside touches to be ignored. Normally if {@link #isDropDownAlwaysVisible()} is
+     * false, we allow outside touch to dismiss the dropdown. If this is set to true, then we
+     * ignore outside touch even when the drop down is not set to always visible.
+     * 
+     * @hide used only by SearchDialog
+     */
+    public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) {
+        mForceIgnoreOutsideTouch = forceIgnoreOutsideTouch;
+    }
 
     /**
      * <p>Builds the popup window's content and returns the height the popup
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 3b9f1de..5e76cc3 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -31,6 +31,7 @@
 import com.android.internal.widget.NumberPicker.OnChangedListener;
 
 import java.text.DateFormatSymbols;
+import java.text.SimpleDateFormat;
 import java.util.Calendar;
 
 /**
@@ -101,7 +102,8 @@
         mMonthPicker = (NumberPicker) findViewById(R.id.month);
         mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
         DateFormatSymbols dfs = new DateFormatSymbols();
-        mMonthPicker.setRange(1, 12, dfs.getShortMonths());
+        String[] months = dfs.getShortMonths();
+        mMonthPicker.setRange(1, 12, months);
         mMonthPicker.setSpeed(200);
         mMonthPicker.setOnChangeListener(new OnChangedListener() {
             public void onChanged(NumberPicker picker, int oldVal, int newVal) {
@@ -146,7 +148,7 @@
         init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), null);
         
         // re-order the number pickers to match the current date format
-        reorderPickers();
+        reorderPickers(months);
         
         if (!isEnabled()) {
             setEnabled(false);
@@ -161,29 +163,69 @@
         mYearPicker.setEnabled(enabled);
     }
 
-    private void reorderPickers() {
-        char[] order = DateFormat.getDateFormatOrder(mContext);
-        
-        /* Default order is month, date, year so if that's the order then
-         * do nothing.
+    private void reorderPickers(String[] months) {
+        java.text.DateFormat format;
+        String order;
+
+        /*
+         * If the user is in a locale where the medium date format is
+         * still numeric (Japanese and Czech, for example), respect
+         * the date format order setting.  Otherwise, use the order
+         * that the locale says is appropriate for a spelled-out date.
          */
-        if ((order[0] == DateFormat.MONTH) && (order[1] == DateFormat.DATE)) {
-            return;
+
+        if (months[0].startsWith("1")) {
+            format = DateFormat.getDateFormat(getContext());
+        } else {
+            format = DateFormat.getMediumDateFormat(getContext());
         }
-        
+
+        if (format instanceof SimpleDateFormat) {
+            order = ((SimpleDateFormat) format).toPattern();
+        } else {
+            // Shouldn't happen, but just in case.
+            order = new String(DateFormat.getDateFormatOrder(getContext()));
+        }
+
         /* Remove the 3 pickers from their parent and then add them back in the
          * required order.
          */
         LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
         parent.removeAllViews();
-        for (char c : order) {
-            if (c == DateFormat.DATE) {
-                parent.addView(mDayPicker);
-            } else if (c == DateFormat.MONTH) {
-                parent.addView(mMonthPicker);
-            } else {
-                parent.addView (mYearPicker);
+
+        boolean quoted = false;
+        boolean didDay = false, didMonth = false, didYear = false;
+
+        for (int i = 0; i < order.length(); i++) {
+            char c = order.charAt(i);
+
+            if (c == '\'') {
+                quoted = !quoted;
             }
+
+            if (!quoted) {
+                if (c == DateFormat.DATE && !didDay) {
+                    parent.addView(mDayPicker);
+                    didDay = true;
+                } else if ((c == DateFormat.MONTH || c == 'L') && !didMonth) {
+                    parent.addView(mMonthPicker);
+                    didMonth = true;
+                } else if (c == DateFormat.YEAR && !didYear) {
+                    parent.addView (mYearPicker);
+                    didYear = true;
+                }
+            }
+        }
+
+        // Shouldn't happen, but just in case.
+        if (!didMonth) {
+            parent.addView(mMonthPicker);
+        }
+        if (!didDay) {
+            parent.addView(mDayPicker);
+        }
+        if (!didYear) {
+            parent.addView(mYearPicker);
         }
     }
 
@@ -192,6 +234,7 @@
         mMonth = monthOfYear;
         mDay = dayOfMonth;
         updateSpinners();
+        reorderPickers(new DateFormatSymbols().getShortMonths());
     }
 
     private static class SavedState extends BaseSavedState {
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 2796774..6a9bcfb 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -317,7 +317,7 @@
     public void setImageBitmap(Bitmap bm) {
         // if this is used frequently, may handle bitmaps explicitly
         // to reduce the intermediate drawable object
-        setImageDrawable(new BitmapDrawable(bm));
+        setImageDrawable(new BitmapDrawable(mContext.getResources(), bm));
     }
 
     public void setImageState(int[] state, boolean merge) {
diff --git a/core/java/com/android/internal/widget/EditStyledText.java b/core/java/com/android/internal/widget/EditStyledText.java
index f0ad7b3..82197c0 100644
--- a/core/java/com/android/internal/widget/EditStyledText.java
+++ b/core/java/com/android/internal/widget/EditStyledText.java
@@ -1242,7 +1242,8 @@
                         try {
                             InputStream is = mEST.getContext().getContentResolver().openInputStream(uri);
                             Bitmap bitmap = BitmapFactory.decodeStream(is);
-                            Drawable drawable = new BitmapDrawable(bitmap);
+                            Drawable drawable = new BitmapDrawable(
+                                    getContext().getResources(), bitmap);
                             drawable.setBounds(0, 0,
                                     drawable.getIntrinsicWidth(),
                                     drawable.getIntrinsicHeight());
diff --git a/core/java/com/google/android/net/GoogleHttpClient.java b/core/java/com/google/android/net/GoogleHttpClient.java
index 922f5be..8a1298f 100644
--- a/core/java/com/google/android/net/GoogleHttpClient.java
+++ b/core/java/com/google/android/net/GoogleHttpClient.java
@@ -58,8 +58,8 @@
  * and otherwise tweak HTTP requests.
  */
 public class GoogleHttpClient implements HttpClient {
-
     private static final String TAG = "GoogleHttpClient";
+    private static final boolean LOCAL_LOGV = Config.LOGV || false;
 
     /** Exception thrown when a request is blocked by the URL rules. */
     public static class BlockedRequestException extends IOException {
@@ -289,9 +289,7 @@
         wrapper.setURI(uri);
         request = wrapper;
 
-        if (Config.LOGV) {
-            Log.v(TAG, "Rule " + rule.mName + ": " + original + " -> " + rewritten);
-        }
+        if (LOCAL_LOGV) Log.v(TAG, "Rule " + rule.mName + ": " + original + " -> " + rewritten);
         return executeWithoutRewriting(request, context);
     }
 
diff --git a/core/java/com/google/android/net/UrlRules.java b/core/java/com/google/android/net/UrlRules.java
index c269d1b..54d139d 100644
--- a/core/java/com/google/android/net/UrlRules.java
+++ b/core/java/com/google/android/net/UrlRules.java
@@ -20,6 +20,7 @@
 import android.database.Cursor;
 import android.provider.Checkin;
 import android.provider.Settings;
+import android.util.Config;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -53,6 +54,9 @@
  * </pre>
  */
 public class UrlRules {
+    public static final String TAG = "UrlRules";
+    public static final boolean LOCAL_LOGV = Config.LOGV || false;
+
     /** Thrown when the rewrite rules can't be parsed. */
     public static class RuleFormatException extends Exception {
         public RuleFormatException(String msg) { super(msg); }
@@ -192,10 +196,11 @@
                 Settings.Gservices.PROVISIONING_DIGEST);
         if (sCachedDigest != null && sCachedDigest.equals(digest)) {
             // The digest is the same, so the rules are the same.
+            if (LOCAL_LOGV) Log.v(TAG, "Using cached rules for digest: " + digest);
             return sCachedRules;
         }
 
-        // Get all the Gservices settings with names starting with "url:".
+        if (LOCAL_LOGV) Log.v(TAG, "Scanning for Gservices \"url:*\" rules");
         Cursor cursor = resolver.query(Settings.Gservices.CONTENT_URI,
                 new String[] {
                     Settings.Gservices.NAME,
@@ -210,16 +215,18 @@
                     String name = cursor.getString(0).substring(4);  // "url:X"
                     String value = cursor.getString(1);
                     if (value == null || value.length() == 0) continue;
+                    if (LOCAL_LOGV) Log.v(TAG, "  Rule " + name + ": " + value);
                     rules.add(new Rule(name, value));
                 } catch (RuleFormatException e) {
                     // Oops, Gservices has an invalid rule!  Skip it.
-                    Log.e("UrlRules", "Invalid rule from Gservices", e);
+                    Log.e(TAG, "Invalid rule from Gservices", e);
                     Checkin.logEvent(resolver,
                         Checkin.Events.Tag.GSERVICES_ERROR, e.toString());
                 }
             }
             sCachedRules = new UrlRules(rules.toArray(new Rule[rules.size()]));
             sCachedDigest = digest;
+            if (LOCAL_LOGV) Log.v(TAG, "New rules stored for digest: " + digest);
         } finally {
             cursor.close();
         }
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index c61b2ed..c16a75e 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -463,17 +463,18 @@
     static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
                                           SkCanvas* canvas, SkBitmap* bitmap,
                                           jfloat left, jfloat top,
-                                          SkPaint* paint,
-                                          jboolean autoScale, jfloat densityScale) {
+                                          SkPaint* paint, jint canvasDensity,
+                                          jint bitmapDensity) {
         SkScalar left_ = SkFloatToScalar(left);
         SkScalar top_ = SkFloatToScalar(top);
 
-        if (!autoScale || densityScale <= 0.0f) {
+        if (canvasDensity == bitmapDensity || canvasDensity == 0
+                || bitmapDensity == 0) {
             canvas->drawBitmap(*bitmap, left_, top_, paint);
         } else {
             canvas->save();
-            SkScalar canvasScale = GraphicsJNI::getCanvasDensityScale(env, jcanvas);
-            SkScalar scale = canvasScale / SkFloatToScalar(densityScale);
+            SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
+            canvas->translate(left_, top_);
             canvas->scale(scale, scale);
 
             SkPaint filteredPaint;
@@ -482,7 +483,7 @@
             }
             filteredPaint.setFilterBitmap(true);
 
-            canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
+            canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
 
             canvas->restore();
         }
@@ -906,7 +907,7 @@
     {"native_drawRoundRect","(ILandroid/graphics/RectF;FFI)V",
         (void*) SkCanvasGlue::drawRoundRect},
     {"native_drawPath","(III)V", (void*) SkCanvasGlue::drawPath},
-    {"native_drawBitmap","(IIFFIZF)V",
+    {"native_drawBitmap","(IIFFIII)V",
         (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
     {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;I)V",
         (void*) SkCanvasGlue::drawBitmapRF},
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 6e159a8..ca1cb7d 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -163,7 +163,6 @@
 
 static jclass   gCanvas_class;
 static jfieldID gCanvas_nativeInstanceID;
-static jfieldID gCanvas_densityScaleID;
 
 static jclass   gPaint_class;
 static jfieldID gPaint_nativeInstanceID;
@@ -320,13 +319,6 @@
     return c;
 }
 
-SkScalar GraphicsJNI::getCanvasDensityScale(JNIEnv* env, jobject canvas) {
-    SkASSERT(env);
-    SkASSERT(canvas);
-    SkASSERT(env->IsInstanceOf(canvas, gCanvas_class));
-    return SkFloatToScalar(env->GetFloatField(canvas, gCanvas_densityScaleID));
-}
-
 SkPaint* GraphicsJNI::getNativePaint(JNIEnv* env, jobject paint) {
     SkASSERT(env);
     SkASSERT(paint);
@@ -557,7 +549,6 @@
 
     gCanvas_class = make_globalref(env, "android/graphics/Canvas");
     gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvas", "I");
-    gCanvas_densityScaleID = getFieldIDCheck(env, gCanvas_class, "mDensityScale", "F");
 
     gPaint_class = make_globalref(env, "android/graphics/Paint");
     gPaint_nativeInstanceID = getFieldIDCheck(env, gPaint_class, "mNativePaint", "I");
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 16925e4..f8b60a8 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -38,7 +38,6 @@
     static SkBitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
     static SkPicture* getNativePicture(JNIEnv*, jobject picture);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
-    static SkScalar getCanvasDensityScale(JNIEnv*, jobject canvas);
     
     /** Return the corresponding native config from the java Config enum,
         or kNo_Config if the java object is null.
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index b11edfc..fd5271e 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -1,5 +1,6 @@
 #include <utils/ResourceTypes.h>
 
+#include "SkCanvas.h"
 #include "SkRegion.h"
 #include "GraphicsJNI.h"
 
@@ -45,7 +46,8 @@
     }
 
     static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds,
-                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint)
+                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
+                      jint destDensity, jint srcDensity)
     {
         size_t chunkSize = env->GetArrayLength(chunkObj);
         void* storage = alloca(chunkSize);
@@ -56,13 +58,32 @@
             Res_png_9patch* chunk = static_cast<Res_png_9patch*>(storage);
             assert(chunkSize == chunk->serializedSize());
             // this relies on deserialization being done in place
-            Res_png_9patch::deserialize(chunk);            
-            NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
+            Res_png_9patch::deserialize(chunk);
+            
+            if (destDensity == srcDensity || destDensity == 0
+                    || srcDensity == 0) {
+                NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
+            } else {
+                canvas->save();
+                
+                SkScalar scale = SkFloatToScalar(destDensity / (float)srcDensity);
+                canvas->translate(bounds.fLeft, bounds.fTop);
+                canvas->scale(scale, scale);
+    
+                bounds.fRight = SkScalarDiv(bounds.fRight-bounds.fLeft, scale);
+                bounds.fBottom = SkScalarDiv(bounds.fBottom-bounds.fTop, scale);
+                bounds.fLeft = bounds.fTop = 0;
+    
+                NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
+    
+                canvas->restore();
+            }
         }
     } 
 
     static void drawF(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRectF,
-                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint)
+                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
+                      jint destDensity, jint srcDensity)
     {
         SkASSERT(canvas);
         SkASSERT(boundsRectF);
@@ -73,11 +94,12 @@
         SkRect      bounds;
         GraphicsJNI::jrectf_to_rect(env, boundsRectF, &bounds);
 
-        draw(env, canvas, bounds, bitmap, chunkObj, paint);
+        draw(env, canvas, bounds, bitmap, chunkObj, paint, destDensity, srcDensity);
     }
  
     static void drawI(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRect,
-                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint)
+                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
+                      jint destDensity, jint srcDensity)
     {
         SkASSERT(canvas);
         SkASSERT(boundsRect);
@@ -87,7 +109,7 @@
 
         SkRect      bounds;
         GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
-        draw(env, canvas, bounds, bitmap, chunkObj, paint);
+        draw(env, canvas, bounds, bitmap, chunkObj, paint, destDensity, srcDensity);
     }
     
     static jint getTransparentRegion(JNIEnv* env, jobject,
@@ -126,8 +148,8 @@
 static JNINativeMethod gNinePatchMethods[] = {
     { "isNinePatchChunk", "([B)Z",                      (void*)SkNinePatchGlue::isNinePatchChunk   },
     { "validateNinePatchChunk", "(I[B)V",               (void*)SkNinePatchGlue::validateNinePatchChunk   },
-    { "nativeDraw", "(ILandroid/graphics/RectF;I[BI)V", (void*)SkNinePatchGlue::drawF   },
-    { "nativeDraw", "(ILandroid/graphics/Rect;I[BI)V",  (void*)SkNinePatchGlue::drawI   },
+    { "nativeDraw", "(ILandroid/graphics/RectF;I[BIII)V", (void*)SkNinePatchGlue::drawF   },
+    { "nativeDraw", "(ILandroid/graphics/Rect;I[BIII)V",  (void*)SkNinePatchGlue::drawI   },
     { "nativeGetTransparentRegion", "(I[BLandroid/graphics/Rect;)I", 
                                                         (void*)SkNinePatchGlue::getTransparentRegion   }
 };
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index d1fe83e..6b7f045 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -48,6 +48,13 @@
 static jclass   gFontMetricsInt_class;
 static JMetricsID gFontMetricsInt_fieldID;
 
+static void defaultSettingsForAndroid(SkPaint* paint) {
+    // looks best we decided
+    paint->setHinting(SkPaint::kSlight_Hinting);
+    // utf16 is required for java
+    paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
+}
+
 class SkPaintGlue {
 public:
 
@@ -57,8 +64,7 @@
 
     static SkPaint* init(JNIEnv* env, jobject clazz) {
         SkPaint* obj = new SkPaint();
-        // utf16 is required for java
-        obj->setTextEncoding(SkPaint::kUTF16_TextEncoding);
+        defaultSettingsForAndroid(obj);
         return obj;
     }
 
@@ -69,8 +75,7 @@
  
     static void reset(JNIEnv* env, jobject clazz, SkPaint* obj) {
         obj->reset();
-        // utf16 is required for java
-        obj->setTextEncoding(SkPaint::kUTF16_TextEncoding);
+        defaultSettingsForAndroid(obj);
     }
  
     static void assign(JNIEnv* env, jobject clazz, SkPaint* dst, const SkPaint* src) {
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 44a9e8c..0be996d 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -28,8 +28,8 @@
 #include "android_runtime/AndroidRuntime.h"
 
 #include "utils/Log.h"
-#include "media/AudioSystem.h"
 #include "media/AudioRecord.h"
+#include "media/mediarecorder.h"
 
 
 // ----------------------------------------------------------------------------
@@ -62,7 +62,7 @@
 #define AUDIORECORD_ERROR_BAD_VALUE                 -2
 #define AUDIORECORD_ERROR_INVALID_OPERATION         -3
 #define AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT      -16
-#define AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT -17
+#define AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK -17
 #define AUDIORECORD_ERROR_SETUP_INVALIDFORMAT       -18
 #define AUDIORECORD_ERROR_SETUP_INVALIDSOURCE       -19
 #define AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED    -20
@@ -122,17 +122,18 @@
 // ----------------------------------------------------------------------------
 static int
 android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
-        jint source, jint sampleRateInHertz, jint nbChannels, 
+        jint source, jint sampleRateInHertz, jint channels,
         jint audioFormat, jint buffSizeInBytes)
 {
     //LOGV(">> Entering android_media_AudioRecord_setup");
-    //LOGV("sampleRate=%d, audioFormat=%d, nbChannels=%d, buffSizeInBytes=%d",
-    //     sampleRateInHertz, audioFormat, nbChannels,     buffSizeInBytes);
+    //LOGV("sampleRate=%d, audioFormat=%d, channels=%x, buffSizeInBytes=%d",
+    //     sampleRateInHertz, audioFormat, channels,     buffSizeInBytes);
 
-    if ((nbChannels == 0) || (nbChannels > 2)) {
+    if (!AudioSystem::isInputChannel(channels)) {
         LOGE("Error creating AudioRecord: channel count is not 1 or 2.");
-        return AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT;
+        return AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK;
     }
+    uint32_t nbChannels = AudioSystem::popCount(channels);
 
     // compare the format against the Java constants
     if ((audioFormat != javaAudioRecordFields.PCM16) 
@@ -152,12 +153,7 @@
     int frameSize = nbChannels * bytesPerSample;
     size_t frameCount = buffSizeInBytes / frameSize;
     
-    // convert and check input source value
-    // input_source values defined in AudioRecord.h are equal to
-    // JAVA MediaRecord.AudioSource values minus 1.
-    AudioRecord::input_source arSource = (AudioRecord::input_source)(source - 1);
-    if (arSource < AudioRecord::DEFAULT_INPUT ||
-        arSource >= AudioRecord::NUM_INPUT_SOURCES) {
+    if (source >= AUDIO_SOURCE_LIST_END) {
         LOGE("Error creating AudioRecord: unknown source.");
         return AUDIORECORD_ERROR_SETUP_INVALIDSOURCE;
     }
@@ -184,10 +180,10 @@
     // we use a weak reference so the AudioRecord object can be garbage collected.
     lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
     
-    lpRecorder->set(arSource,
+    lpRecorder->set(source,
         sampleRateInHertz,
         format,        // word length, PCM
-        nbChannels,
+        channels,
         frameCount,
         0,             // flags
         recorderCallback,// callback_t
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 692610e..3d8d296 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -50,25 +50,6 @@
 }
 
 static int
-android_media_AudioSystem_setVolume(JNIEnv *env, jobject clazz, jint type, jint volume)
-{
-    LOGV("setVolume(%d)", int(volume));
-    
-    return check_AudioSystem_Command(AudioSystem::setStreamVolume(type, AudioSystem::linearToLog(volume)));
-}
-
-static int
-android_media_AudioSystem_getVolume(JNIEnv *env, jobject clazz, jint type)
-{
-    float v;
-    int v_int = -1;
-    if (AudioSystem::getStreamVolume(int(type), &v) == NO_ERROR) {
-        v_int = AudioSystem::logToLinear(v);
-    }
-    return v_int;
-}
-
-static int
 android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
 {
     return check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
@@ -82,34 +63,6 @@
     return state;
 }
 
-static int
-android_media_AudioSystem_setRouting(JNIEnv *env, jobject clazz, jint mode, jint routes, jint mask)
-{
-    return check_AudioSystem_Command(AudioSystem::setRouting(mode, uint32_t(routes), uint32_t(mask)));
-}
-
-static jint
-android_media_AudioSystem_getRouting(JNIEnv *env, jobject clazz, jint mode)
-{
-    uint32_t routes = -1;
-    AudioSystem::getRouting(mode, &routes);
-    return jint(routes);
-}
-
-static int
-android_media_AudioSystem_setMode(JNIEnv *env, jobject clazz, jint mode)
-{
-    return check_AudioSystem_Command(AudioSystem::setMode(mode));
-}
-
-static jint
-android_media_AudioSystem_getMode(JNIEnv *env, jobject clazz)
-{
-    int mode = AudioSystem::MODE_INVALID;
-    AudioSystem::getMode(&mode);
-    return jint(mode);
-}
-
 static jboolean
 android_media_AudioSystem_isMusicActive(JNIEnv *env, jobject thiz)
 {
@@ -118,16 +71,29 @@
     return state;
 }
 
-// Temporary interface, do not use
-// TODO: Replace with a more generic key:value get/set mechanism
-static void
-android_media_AudioSystem_setParameter(JNIEnv *env, jobject thiz, jstring key, jstring value)
+static int
+android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
 {
-    const char *c_key = env->GetStringUTFChars(key, NULL);
-    const char *c_value = env->GetStringUTFChars(value, NULL);
-    AudioSystem::setParameter(c_key, c_value);
-    env->ReleaseStringUTFChars(key, c_key);
-    env->ReleaseStringUTFChars(value, c_value);
+    const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
+    String8 c_keyValuePairs8;
+    if (keyValuePairs) {
+        c_keyValuePairs8 = String8(c_keyValuePairs, env->GetStringLength(keyValuePairs));
+        env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
+    }
+    int status = check_AudioSystem_Command(AudioSystem::setParameters(0, c_keyValuePairs8));
+    return status;
+}
+
+static jstring
+android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
+{
+    const jchar* c_keys = env->GetStringCritical(keys, 0);
+    String8 c_keys8;
+    if (keys) {
+        c_keys8 = String8(c_keys, env->GetStringLength(keys));
+        env->ReleaseStringCritical(keys, c_keys);
+    }
+    return env->NewStringUTF(AudioSystem::getParameters(0, c_keys8).string());
 }
 
 void android_media_AudioSystem_error_callback(status_t err)
@@ -152,19 +118,93 @@
     env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error);
 }
 
+static int
+android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address)
+{
+    const char *c_address = env->GetStringUTFChars(device_address, NULL);
+    int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <AudioSystem::audio_devices>(device),
+                                          static_cast <AudioSystem::device_connection_state>(state),
+                                          c_address));
+    env->ReleaseStringUTFChars(device_address, c_address);
+    return status;
+}
+
+static int
+android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
+{
+    const char *c_address = env->GetStringUTFChars(device_address, NULL);
+    int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <AudioSystem::audio_devices>(device),
+                                          c_address));
+    env->ReleaseStringUTFChars(device_address, c_address);
+    return state;
+}
+
+static int
+android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
+{
+    return check_AudioSystem_Command(AudioSystem::setPhoneState(state));
+}
+
+static int
+android_media_AudioSystem_setRingerMode(JNIEnv *env, jobject thiz, jint mode, jint mask)
+{
+    return check_AudioSystem_Command(AudioSystem::setRingerMode(mode, mask));
+}
+
+static int
+android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
+{
+    return check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <AudioSystem::force_use>(usage),
+                                                           static_cast <AudioSystem::forced_config>(config)));
+}
+
+static int
+android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
+{
+    return static_cast <int>(AudioSystem::getForceUse(static_cast <AudioSystem::force_use>(usage)));
+}
+
+static int
+android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
+{
+    return check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <AudioSystem::stream_type>(stream),
+                                                                   indexMin,
+                                                                   indexMax));
+}
+
+static int
+android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env, jobject thiz, jint stream, jint index)
+{
+    return check_AudioSystem_Command(AudioSystem::setStreamVolumeIndex(static_cast <AudioSystem::stream_type>(stream), index));
+}
+
+static int
+android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env, jobject thiz, jint stream)
+{
+    int index;
+    if (AudioSystem::getStreamVolumeIndex(static_cast <AudioSystem::stream_type>(stream), &index) != NO_ERROR) {
+        index = -1;
+    }
+    return index;
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
-    {"setVolume",           "(II)I",    (void *)android_media_AudioSystem_setVolume},
-    {"getVolume",           "(I)I",     (void *)android_media_AudioSystem_getVolume},
-    {"setParameter",        "(Ljava/lang/String;Ljava/lang/String;)V", (void *)android_media_AudioSystem_setParameter},
+    {"setParameters",        "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
+    {"getParameters",        "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
     {"muteMicrophone",      "(Z)I",     (void *)android_media_AudioSystem_muteMicrophone},
     {"isMicrophoneMuted",   "()Z",      (void *)android_media_AudioSystem_isMicrophoneMuted},
-    {"setRouting",          "(III)I",   (void *)android_media_AudioSystem_setRouting},
-    {"getRouting",          "(I)I",     (void *)android_media_AudioSystem_getRouting},
-    {"setMode",             "(I)I",     (void *)android_media_AudioSystem_setMode},
-    {"getMode",             "()I",      (void *)android_media_AudioSystem_getMode},
     {"isMusicActive",       "()Z",      (void *)android_media_AudioSystem_isMusicActive},
+    {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
+    {"getDeviceConnectionState", "(ILjava/lang/String;)I",  (void *)android_media_AudioSystem_getDeviceConnectionState},
+    {"setPhoneState",       "(I)I",     (void *)android_media_AudioSystem_setPhoneState},
+    {"setRingerMode",       "(II)I",    (void *)android_media_AudioSystem_setRingerMode},
+    {"setForceUse",         "(II)I",    (void *)android_media_AudioSystem_setForceUse},
+    {"getForceUse",         "(I)I",     (void *)android_media_AudioSystem_getForceUse},
+    {"initStreamVolume",    "(III)I",   (void *)android_media_AudioSystem_initStreamVolume},
+    {"setStreamVolumeIndex","(II)I",    (void *)android_media_AudioSystem_setStreamVolumeIndex},
+    {"getStreamVolumeIndex","(I)I",     (void *)android_media_AudioSystem_getStreamVolumeIndex}
 };
 
 const char* const kClassPathName = "android/media/AudioSystem";
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index bc7f3f5..6449147 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -103,7 +103,7 @@
 #define AUDIOTRACK_ERROR_BAD_VALUE                 -2
 #define AUDIOTRACK_ERROR_INVALID_OPERATION         -3
 #define AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM         -16
-#define AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELCOUNT -17
+#define AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK -17
 #define AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT       -18
 #define AUDIOTRACK_ERROR_SETUP_INVALIDSTREAMTYPE   -19
 #define AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED    -20
@@ -164,11 +164,11 @@
 // ----------------------------------------------------------------------------
 static int
 android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
-        jint streamType, jint sampleRateInHertz, jint nbChannels, 
+        jint streamType, jint sampleRateInHertz, jint channels,
         jint audioFormat, jint buffSizeInBytes, jint memoryMode)
 {
-    LOGV("sampleRate=%d, audioFormat(from Java)=%d, nbChannels=%d, buffSize=%d", 
-        sampleRateInHertz, audioFormat, nbChannels, buffSizeInBytes);
+    LOGV("sampleRate=%d, audioFormat(from Java)=%d, channels=%x, buffSize=%d",
+        sampleRateInHertz, audioFormat, channels, buffSizeInBytes);
     int afSampleRate;
     int afFrameCount;
 
@@ -181,10 +181,11 @@
         return AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM;
     }
 
-    if ((nbChannels == 0) || (nbChannels > 2)) {
-        LOGE("Error creating AudioTrack: channel count is not 1 or 2.");
-        return AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELCOUNT;
+    if (!AudioSystem::isOutputChannel(channels)) {
+        LOGE("Error creating AudioTrack: invalid channel mask.");
+        return AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
     }
+    int nbChannels = AudioSystem::popCount(channels);
     
     // check the stream type
     AudioSystem::stream_type atStreamType;
@@ -231,15 +232,7 @@
     int bytesPerSample = audioFormat == javaAudioTrackFields.PCM16 ? 2 : 1;
     int format = audioFormat == javaAudioTrackFields.PCM16 ? 
             AudioSystem::PCM_16_BIT : AudioSystem::PCM_8_BIT;
-    int frameCount;
-    if (buffSizeInBytes == -1) {
-        // compute the frame count based on the system's output frame count 
-        // and the native sample rate
-        frameCount = (sampleRateInHertz*afFrameCount)/afSampleRate;
-    } else {
-        // compute the frame count based on the specified buffer size
-        frameCount = buffSizeInBytes / (nbChannels * bytesPerSample);
-    }
+    int frameCount = buffSizeInBytes / (nbChannels * bytesPerSample);
     
     AudioTrackJniStorage* lpJniStorage = new AudioTrackJniStorage();
     
@@ -271,7 +264,7 @@
             atStreamType,// stream type
             sampleRateInHertz,
             format,// word length, PCM
-            nbChannels,
+            channels,
             frameCount,
             0,// flags
             audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
@@ -291,7 +284,7 @@
             atStreamType,// stream type
             sampleRateInHertz,
             format,// word length, PCM
-            nbChannels,
+            channels,
             frameCount,
             0,// flags
             audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 027fb23..9d55dab 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -25,7 +25,7 @@
     <!-- Special broadcasts that only the system can send -->
     <!-- ================================================ -->
     <eat-comment />
-    
+
     <protected-broadcast android:name="android.intent.action.SCREEN_OFF" />
     <protected-broadcast android:name="android.intent.action.SCREEN_ON" />
     <protected-broadcast android:name="android.intent.action.USER_PRESENT" />
@@ -52,7 +52,7 @@
     <protected-broadcast android:name="android.intent.action.AIRPLANE_MODE" />
     <protected-broadcast android:name="android.intent.action.NEW_OUTGOING_CALL" />
     <protected-broadcast android:name="android.intent.action.REBOOT" />
-    
+
     <!-- ====================================== -->
     <!-- Permissions for things that cost money -->
     <!-- ====================================== -->
@@ -309,6 +309,14 @@
         android:description="@string/permdesc_bluetooth"
         android:label="@string/permlab_bluetooth" />
 
+    <!-- Allows applications to call into AccountAuthenticators. Only
+    the system can get this permission. -->
+    <permission android:name="android.permission.ACCOUNT_MANAGER_SERVICE"
+        android:permissionGroup="android.permission-group.ACCOUNTS"
+        android:protectionLevel="signature"
+        android:description="@string/permdesc_accountManagerService"
+        android:label="@string/permlab_accountManagerService" />
+
     <!-- ================================== -->
     <!-- Permissions for accessing accounts -->
     <!-- ================================== -->
@@ -330,6 +338,28 @@
         android:description="@string/permdesc_getAccounts"
         android:label="@string/permlab_getAccounts" />
 
+    <!-- Allows an application to act as an AccountAuthenticator for
+         the AccountManager -->
+    <permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
+        android:permissionGroup="android.permission-group.ACCOUNTS"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_authenticateAccounts"
+        android:description="@string/permdesc_authenticateAccounts" />
+
+    <!-- Allows an application to request authtokens from the AccountManager -->
+    <permission android:name="android.permission.USE_CREDENTIALS"
+        android:permissionGroup="android.permission-group.ACCOUNTS"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_useCredentials"
+        android:description="@string/permdesc_useCredentials" />
+
+    <!-- Allows an application to manage the list of accounts in the AccountManager -->
+    <permission android:name="android.permission.MANAGE_ACCOUNTS"
+        android:permissionGroup="android.permission-group.ACCOUNTS"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_manageAccounts"
+        android:description="@string/permdesc_manageAccounts" />
+
     <!-- ================================== -->
     <!-- Permissions for accessing hardware -->
     <!-- ================================== -->
@@ -1093,6 +1123,11 @@
                 android:exported="true">
         </activity>
 
+        <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
+                android:excludeFromRecents="true"
+                android:exported="true">
+        </activity>
+
         <service android:name="com.android.server.LoadAverageService"
             android:exported="true" />
 
diff --git a/core/res/res/layout/grant_credentials_permission.xml b/core/res/res/layout/grant_credentials_permission.xml
new file mode 100644
index 0000000..fe1c22e
--- /dev/null
+++ b/core/res/res/layout/grant_credentials_permission.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/message" />
+    <Button android:id="@+id/allow"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/allow" />
+
+    <Button android:id="@+id/deny"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/deny" />
+
+    <ListView android:id="@+id/packages_list"
+       android:layout_width="fill_parent" android:layout_height="fill_parent"/>
+
+</LinearLayout>
diff --git a/core/res/res/values-bg-rBG/donottranslate-cldr.xml b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
index b8b50cc..527cdb9 100644
--- a/core/res/res/values-bg-rBG/donottranslate-cldr.xml
+++ b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
@@ -111,7 +111,7 @@
     <string name="abbrev_month_day">%-e %b</string>
     <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
+    <string name="time1_time2">%1$s-%2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
     <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
     <string name="numeric_wday1_md1_wday2_md2">%3$s.%2$s, %1$s - %8$s.%7$s, %6$s</string>
diff --git a/core/res/res/values-cs-rCZ/donottranslate-cldr.xml b/core/res/res/values-cs-rCZ/donottranslate-cldr.xml
deleted file mode 100644
index 41f5dea..0000000
--- a/core/res/res/values-cs-rCZ/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">leden</string>
-    <string name="month_long_standalone_february">únor</string>
-    <string name="month_long_standalone_march">březen</string>
-    <string name="month_long_standalone_april">duben</string>
-    <string name="month_long_standalone_may">květen</string>
-    <string name="month_long_standalone_june">červen</string>
-    <string name="month_long_standalone_july">červenec</string>
-    <string name="month_long_standalone_august">srpen</string>
-    <string name="month_long_standalone_september">září</string>
-    <string name="month_long_standalone_october">říjen</string>
-    <string name="month_long_standalone_november">listopad</string>
-    <string name="month_long_standalone_december">prosinec</string>
-
-    <string name="month_long_january">ledna</string>
-    <string name="month_long_february">února</string>
-    <string name="month_long_march">března</string>
-    <string name="month_long_april">dubna</string>
-    <string name="month_long_may">května</string>
-    <string name="month_long_june">června</string>
-    <string name="month_long_july">července</string>
-    <string name="month_long_august">srpna</string>
-    <string name="month_long_september">září</string>
-    <string name="month_long_october">října</string>
-    <string name="month_long_november">listopadu</string>
-    <string name="month_long_december">prosince</string>
-
-    <string name="month_medium_january">1</string>
-    <string name="month_medium_february">2</string>
-    <string name="month_medium_march">3</string>
-    <string name="month_medium_april">4</string>
-    <string name="month_medium_may">5</string>
-    <string name="month_medium_june">6</string>
-    <string name="month_medium_july">7</string>
-    <string name="month_medium_august">8</string>
-    <string name="month_medium_september">9</string>
-    <string name="month_medium_october">10</string>
-    <string name="month_medium_november">11</string>
-    <string name="month_medium_december">12</string>
-
-    <string name="month_shortest_january">l</string>
-    <string name="month_shortest_february">ú</string>
-    <string name="month_shortest_march">b</string>
-    <string name="month_shortest_april">d</string>
-    <string name="month_shortest_may">k</string>
-    <string name="month_shortest_june">č</string>
-    <string name="month_shortest_july">č</string>
-    <string name="month_shortest_august">s</string>
-    <string name="month_shortest_september">z</string>
-    <string name="month_shortest_october">ř</string>
-    <string name="month_shortest_november">l</string>
-    <string name="month_shortest_december">p</string>
-
-    <string name="day_of_week_long_sunday">neděle</string>
-    <string name="day_of_week_long_monday">pondělí</string>
-    <string name="day_of_week_long_tuesday">úterý</string>
-    <string name="day_of_week_long_wednesday">středa</string>
-    <string name="day_of_week_long_thursday">čtvrtek</string>
-    <string name="day_of_week_long_friday">pátek</string>
-    <string name="day_of_week_long_saturday">sobota</string>
-
-    <string name="day_of_week_medium_sunday">ne</string>
-    <string name="day_of_week_medium_monday">po</string>
-    <string name="day_of_week_medium_tuesday">út</string>
-    <string name="day_of_week_medium_wednesday">st</string>
-    <string name="day_of_week_medium_thursday">čt</string>
-    <string name="day_of_week_medium_friday">pá</string>
-    <string name="day_of_week_medium_saturday">so</string>
-
-    <string name="day_of_week_short_sunday">ne</string>
-    <string name="day_of_week_short_monday">po</string>
-    <string name="day_of_week_short_tuesday">út</string>
-    <string name="day_of_week_short_wednesday">st</string>
-    <string name="day_of_week_short_thursday">čt</string>
-    <string name="day_of_week_short_friday">pá</string>
-    <string name="day_of_week_short_saturday">so</string>
-
-    <string name="day_of_week_shortest_sunday">N</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">Ú</string>
-    <string name="day_of_week_shortest_wednesday">S</string>
-    <string name="day_of_week_shortest_thursday">Č</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">dop.</string>
-    <string name="pm">odp.</string>
-    <string name="yesterday">Včera</string>
-    <string name="today">Dnes</string>
-    <string name="tomorrow">Zítra</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%-e.%-m.%Y</string>
-    <string name="numeric_date_format">d.M.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
-    <string name="month_day_year">%-e. %B %Y</string>
-    <string name="time_of_day">%-k:%M:%S</string>
-    <string name="date_and_time">%-k:%M:%S %-e.%-m.%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
-    <string name="month_day">%-e. %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%-B %Y</string>
-    <string name="abbrev_month_day">%-e.%-m</string>
-    <string name="abbrev_month">%-B</string>
-    <string name="abbrev_month_year">%-B %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="short_format_month">%B</string>
-</resources>
diff --git a/core/res/res/values-cs/donottranslate-cldr.xml b/core/res/res/values-cs/donottranslate-cldr.xml
index 41f5dea..53dc312 100644
--- a/core/res/res/values-cs/donottranslate-cldr.xml
+++ b/core/res/res/values-cs/donottranslate-cldr.xml
@@ -27,18 +27,18 @@
     <string name="month_long_november">listopadu</string>
     <string name="month_long_december">prosince</string>
 
-    <string name="month_medium_january">1</string>
-    <string name="month_medium_february">2</string>
-    <string name="month_medium_march">3</string>
-    <string name="month_medium_april">4</string>
-    <string name="month_medium_may">5</string>
-    <string name="month_medium_june">6</string>
-    <string name="month_medium_july">7</string>
-    <string name="month_medium_august">8</string>
-    <string name="month_medium_september">9</string>
-    <string name="month_medium_october">10</string>
-    <string name="month_medium_november">11</string>
-    <string name="month_medium_december">12</string>
+    <string name="month_medium_january">1.</string>
+    <string name="month_medium_february">2.</string>
+    <string name="month_medium_march">3.</string>
+    <string name="month_medium_april">4.</string>
+    <string name="month_medium_may">5.</string>
+    <string name="month_medium_june">6.</string>
+    <string name="month_medium_july">7.</string>
+    <string name="month_medium_august">8.</string>
+    <string name="month_medium_september">9.</string>
+    <string name="month_medium_october">10.</string>
+    <string name="month_medium_november">11.</string>
+    <string name="month_medium_december">12.</string>
 
     <string name="month_shortest_january">l</string>
     <string name="month_shortest_february">ú</string>
@@ -96,52 +96,52 @@
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
     <string name="twelve_hour_time_format">h:mm a</string>
     <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%-e.%-m.%Y</string>
-    <string name="numeric_date_format">d.M.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
+    <string name="numeric_date">%-e. %-m. %Y</string>
+    <string name="numeric_date_format">d. M. yyyy</string>
+    <string name="numeric_date_template">"%s. %s. %s"</string>
     <string name="month_day_year">%-e. %B %Y</string>
     <string name="time_of_day">%-k:%M:%S</string>
-    <string name="date_and_time">%-k:%M:%S %-e.%-m.%Y</string>
+    <string name="date_and_time">%-k:%M:%S %-e. %-m. %Y</string>
     <string name="date_time">%2$s %1$s</string>
     <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
+    <string name="abbrev_month_day_year">%-e. %-m. %Y</string>
     <string name="month_day">%-e. %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%-B %Y</string>
-    <string name="abbrev_month_day">%-e.%-m</string>
+    <string name="abbrev_month_day">%-e. %-m.</string>
     <string name="abbrev_month">%-B</string>
     <string name="abbrev_month_year">%-B %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
+    <string name="time1_time2">%1$s-%2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="numeric_md1_md2">%3$s. %2$s. - %8$s. %7$s.</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s. %2$s. - %6$s %8$s. %7$s.</string>
+    <string name="numeric_mdy1_mdy2">%3$s. %2$s. %4$s - %8$s. %7$s. %9$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s. %4$s - %6$s %8$s. %7$s. %9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s. %4$s - %10$s %6$s %8$s. %7$s. %9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s. %2$s. - %10$s %8$s. %7$s.</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s. - %10$s %6$s %8$s. %7$s.</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s - %10$s %8$s. %7$s. %9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
     <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday_date">%1$s %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
     <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
     <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s - %10$s %6$s %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s - %10$s %6$s %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s %4$s - %6$s %8$s. %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="short_format_month">%B</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s - %6$s %8$s. %7$s %9$s</string>
+    <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index bbb3a7d..0d6137b 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"K souboru nelze získat přístup."</string>
     <string name="httpErrorFileNotFound">"Požadovaný soubor nebyl nalezen."</string>
     <string name="httpErrorTooManyRequests">"Je zpracováváno příliš mnoho požadavků. Opakujte akci později."</string>
-    <string name="certificateSaved">"Certifikát je uložen v systémovém úložišti klíčů."</string>
     <string name="contentServiceSync">"Synchronizace"</string>
     <string name="contentServiceSyncNotificationTitle">"Synchronizace"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Příliš mnoho smazaných položek služby <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-da-rDK/donottranslate-cldr.xml b/core/res/res/values-da-rDK/donottranslate-cldr.xml
deleted file mode 100644
index 2d0db938..0000000
--- a/core/res/res/values-da-rDK/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januar</string>
-    <string name="month_long_standalone_february">februar</string>
-    <string name="month_long_standalone_march">marts</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">maj</string>
-    <string name="month_long_standalone_june">juni</string>
-    <string name="month_long_standalone_july">juli</string>
-    <string name="month_long_standalone_august">august</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januar</string>
-    <string name="month_long_february">februar</string>
-    <string name="month_long_march">marts</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">maj</string>
-    <string name="month_long_june">juni</string>
-    <string name="month_long_july">juli</string>
-    <string name="month_long_august">august</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mar.</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">maj</string>
-    <string name="month_medium_june">jun.</string>
-    <string name="month_medium_july">jul.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sep.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">søndag</string>
-    <string name="day_of_week_long_monday">mandag</string>
-    <string name="day_of_week_long_tuesday">tirsdag</string>
-    <string name="day_of_week_long_wednesday">onsdag</string>
-    <string name="day_of_week_long_thursday">torsdag</string>
-    <string name="day_of_week_long_friday">fredag</string>
-    <string name="day_of_week_long_saturday">lørdag</string>
-
-    <string name="day_of_week_medium_sunday">søn</string>
-    <string name="day_of_week_medium_monday">man</string>
-    <string name="day_of_week_medium_tuesday">tir</string>
-    <string name="day_of_week_medium_wednesday">ons</string>
-    <string name="day_of_week_medium_thursday">tor</string>
-    <string name="day_of_week_medium_friday">fre</string>
-    <string name="day_of_week_medium_saturday">lør</string>
-
-    <string name="day_of_week_short_sunday">søn</string>
-    <string name="day_of_week_short_monday">man</string>
-    <string name="day_of_week_short_tuesday">tir</string>
-    <string name="day_of_week_short_wednesday">ons</string>
-    <string name="day_of_week_short_thursday">tor</string>
-    <string name="day_of_week_short_friday">fre</string>
-    <string name="day_of_week_short_saturday">lør</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">O</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">L</string>
-
-    <string name="am">f.m.</string>
-    <string name="pm">e.m.</string>
-    <string name="yesterday">i går</string>
-    <string name="today">i dag</string>
-    <string name="tomorrow">i morgen</string>
-
-    <string name="hour_minute_24">%H.%M</string>
-    <string name="hour_minute_ampm">%-l.%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l.%M %^p</string>
-    <string name="twelve_hour_time_format">h.mm a</string>
-    <string name="twenty_four_hour_time_format">HH.mm</string>
-    <string name="numeric_date">%d/%m/%Y</string>
-    <string name="numeric_date_format">dd/MM/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e. %b %Y</string>
-    <string name="time_of_day">%H.%M.%S</string>
-    <string name="date_and_time">%H.%M.%S %d/%m/%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d/%m/%Y</string>
-    <string name="month_day">%-e. %B</string>
-    <string name="month">%B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e. %b</string>
-    <string name="abbrev_month">%b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s. %3$s-%2$s-%4$s - %10$s %6$s. %8$s-%7$s-%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s. %3$s-%2$s - %10$s %6$s. %8$s-%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s den %2$s - %6$s %4$s den %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s den %2$s - %4$s den %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s den %3$s</string>
-    <string name="wday_date">%2$s den %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s. %3$s. %2$s %4$s - %10$s %6$s. %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s. %3$s. %2$s %4$s - %10$s %6$s. %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s. %3$s. %2$s %4$s - %6$s. %8$s. %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s den %3$s. %2$s - %6$s den %8$s. %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-da/donottranslate-cldr.xml b/core/res/res/values-da/donottranslate-cldr.xml
index 2d0db938..a4faca2 100644
--- a/core/res/res/values-da/donottranslate-cldr.xml
+++ b/core/res/res/values-da/donottranslate-cldr.xml
@@ -61,21 +61,21 @@
     <string name="day_of_week_long_friday">fredag</string>
     <string name="day_of_week_long_saturday">lørdag</string>
 
-    <string name="day_of_week_medium_sunday">søn</string>
-    <string name="day_of_week_medium_monday">man</string>
-    <string name="day_of_week_medium_tuesday">tir</string>
-    <string name="day_of_week_medium_wednesday">ons</string>
-    <string name="day_of_week_medium_thursday">tor</string>
-    <string name="day_of_week_medium_friday">fre</string>
-    <string name="day_of_week_medium_saturday">lør</string>
+    <string name="day_of_week_medium_sunday">søn.</string>
+    <string name="day_of_week_medium_monday">man.</string>
+    <string name="day_of_week_medium_tuesday">tir.</string>
+    <string name="day_of_week_medium_wednesday">ons.</string>
+    <string name="day_of_week_medium_thursday">tor.</string>
+    <string name="day_of_week_medium_friday">fre.</string>
+    <string name="day_of_week_medium_saturday">lør.</string>
 
-    <string name="day_of_week_short_sunday">søn</string>
-    <string name="day_of_week_short_monday">man</string>
-    <string name="day_of_week_short_tuesday">tir</string>
-    <string name="day_of_week_short_wednesday">ons</string>
-    <string name="day_of_week_short_thursday">tor</string>
-    <string name="day_of_week_short_friday">fre</string>
-    <string name="day_of_week_short_saturday">lør</string>
+    <string name="day_of_week_short_sunday">søn.</string>
+    <string name="day_of_week_short_monday">man.</string>
+    <string name="day_of_week_short_tuesday">tir.</string>
+    <string name="day_of_week_short_wednesday">ons.</string>
+    <string name="day_of_week_short_thursday">tor.</string>
+    <string name="day_of_week_short_friday">fre.</string>
+    <string name="day_of_week_short_saturday">lør.</string>
 
     <string name="day_of_week_shortest_sunday">S</string>
     <string name="day_of_week_shortest_monday">M</string>
@@ -91,20 +91,20 @@
     <string name="today">i dag</string>
     <string name="tomorrow">i morgen</string>
 
-    <string name="hour_minute_24">%H.%M</string>
+    <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l.%M %p</string>
     <string name="hour_minute_cap_ampm">%-l.%M %^p</string>
     <string name="twelve_hour_time_format">h.mm a</string>
-    <string name="twenty_four_hour_time_format">HH.mm</string>
+    <string name="twenty_four_hour_time_format">HH:mm</string>
     <string name="numeric_date">%d/%m/%Y</string>
     <string name="numeric_date_format">dd/MM/yyyy</string>
     <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e. %b %Y</string>
-    <string name="time_of_day">%H.%M.%S</string>
-    <string name="date_and_time">%H.%M.%S %d/%m/%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d/%m/%Y</string>
+    <string name="month_day_year">%-e. %B %Y</string>
+    <string name="time_of_day">%H:%M:%S</string>
+    <string name="date_and_time">%H:%M:%S, %-e. %b %Y</string>
+    <string name="date_time">%2$s, %1$s</string>
+    <string name="time_date">%1$s, %3$s</string>
+    <string name="abbrev_month_day_year">%-e. %b %Y</string>
     <string name="month_day">%-e. %B</string>
     <string name="month">%B</string>
     <string name="month_year">%B %Y</string>
@@ -117,31 +117,31 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s. %3$s-%2$s-%4$s - %10$s %6$s. %8$s-%7$s-%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s. %3$s-%2$s - %10$s %6$s. %8$s-%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s den %2$s - %6$s %4$s den %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s den %2$s - %4$s den %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s den %3$s</string>
-    <string name="wday_date">%2$s den %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s %3$s/%2$s/%4$s - %10$s, %6$s %8$s/%7$s/%9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s, %3$s/%2$s - %10$s, %8$s/%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s %3$s/%2$s - %10$s, %6$s %8$s/%7$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s, %3$s/%2$s/%4$s - %10$s, %8$s/%7$s/%9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s, %1$s %2$s - %6$s, %4$s %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s, %2$s - %6$s, %5$s</string>
+    <string name="time_wday_date">%1$s, %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday">%1$s, %2$s</string>
     <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s. %3$s. %2$s %4$s - %10$s %6$s. %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s. %3$s. %2$s %4$s - %10$s %6$s. %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s. %3$s. %2$s %4$s - %6$s. %8$s. %7$s %9$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s, %3$s. %2$s - %10$s, %8$s. %7$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s, %3$s. %2$s - %10$s, %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s %3$s. %2$s - %10$s, %6$s %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s %3$s. %2$s - %10$s, %6$s %8$s. %7$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s, %3$s. %2$s %4$s - %10$s, %8$s. %7$s %9$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s, %3$s. %2$s %4$s - %10$s, %8$s. %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s %3$s. %2$s %4$s - %10$s, %6$s %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s %3$s. %2$s %4$s - %10$s, %6$s %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s %4$s - %6$s %8$s. %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s den %3$s. %2$s - %6$s den %8$s. %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s d. %3$s. %2$s - %6$s d. %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index cb8fa78..4add1f8 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Der kunne ikke oprettes adgang til filen."</string>
     <string name="httpErrorFileNotFound">"Den anmodede fil blev ikke fundet."</string>
     <string name="httpErrorTooManyRequests">"Der behandles for mange anmodninger. Prøv igen senere."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Synkroniser"</string>
     <string name="contentServiceSyncNotificationTitle">"Synkroniser"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"For mange <xliff:g id="CONTENT_TYPE">%s</xliff:g> sletninger"</string>
diff --git a/core/res/res/values-de-rAT/donottranslate-cldr.xml b/core/res/res/values-de-rAT/donottranslate-cldr.xml
deleted file mode 100644
index 27624a3..0000000
--- a/core/res/res/values-de-rAT/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Jänner</string>
-    <string name="month_long_standalone_february">Februar</string>
-    <string name="month_long_standalone_march">März</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">Mai</string>
-    <string name="month_long_standalone_june">Juni</string>
-    <string name="month_long_standalone_july">Juli</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">Oktober</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">Dezember</string>
-
-    <string name="month_long_january">Jänner</string>
-    <string name="month_long_february">Februar</string>
-    <string name="month_long_march">März</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">Mai</string>
-    <string name="month_long_june">Juni</string>
-    <string name="month_long_july">Juli</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">Oktober</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">Dezember</string>
-
-    <string name="month_medium_january">Jän</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mär</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mai</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dez</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sonntag</string>
-    <string name="day_of_week_long_monday">Montag</string>
-    <string name="day_of_week_long_tuesday">Dienstag</string>
-    <string name="day_of_week_long_wednesday">Mittwoch</string>
-    <string name="day_of_week_long_thursday">Donnerstag</string>
-    <string name="day_of_week_long_friday">Freitag</string>
-    <string name="day_of_week_long_saturday">Samstag</string>
-
-    <string name="day_of_week_medium_sunday">So.</string>
-    <string name="day_of_week_medium_monday">Mo.</string>
-    <string name="day_of_week_medium_tuesday">Di.</string>
-    <string name="day_of_week_medium_wednesday">Mi.</string>
-    <string name="day_of_week_medium_thursday">Do.</string>
-    <string name="day_of_week_medium_friday">Fr.</string>
-    <string name="day_of_week_medium_saturday">Sa.</string>
-
-    <string name="day_of_week_short_sunday">So.</string>
-    <string name="day_of_week_short_monday">Mo.</string>
-    <string name="day_of_week_short_tuesday">Di.</string>
-    <string name="day_of_week_short_wednesday">Mi.</string>
-    <string name="day_of_week_short_thursday">Do.</string>
-    <string name="day_of_week_short_friday">Fr.</string>
-    <string name="day_of_week_short_saturday">Sa.</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">D</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">D</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">vorm.</string>
-    <string name="pm">nachm.</string>
-    <string name="yesterday">Gestern</string>
-    <string name="today">Heute</string>
-    <string name="tomorrow">Morgen</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d.%m.%Y</string>
-    <string name="numeric_date_format">dd.MM.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
-    <string name="month_day_year">%d. %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d.%m.%Y</string>
-    <string name="month_day">%-e. %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%d. %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-de-rCH/donottranslate-cldr.xml b/core/res/res/values-de-rCH/donottranslate-cldr.xml
deleted file mode 100644
index f32095b..0000000
--- a/core/res/res/values-de-rCH/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Januar</string>
-    <string name="month_long_standalone_february">Februar</string>
-    <string name="month_long_standalone_march">März</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">Mai</string>
-    <string name="month_long_standalone_june">Juni</string>
-    <string name="month_long_standalone_july">Juli</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">Oktober</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">Dezember</string>
-
-    <string name="month_long_january">Januar</string>
-    <string name="month_long_february">Februar</string>
-    <string name="month_long_march">März</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">Mai</string>
-    <string name="month_long_june">Juni</string>
-    <string name="month_long_july">Juli</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">Oktober</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">Dezember</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mär</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mai</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dez</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sonntag</string>
-    <string name="day_of_week_long_monday">Montag</string>
-    <string name="day_of_week_long_tuesday">Dienstag</string>
-    <string name="day_of_week_long_wednesday">Mittwoch</string>
-    <string name="day_of_week_long_thursday">Donnerstag</string>
-    <string name="day_of_week_long_friday">Freitag</string>
-    <string name="day_of_week_long_saturday">Samstag</string>
-
-    <string name="day_of_week_medium_sunday">So.</string>
-    <string name="day_of_week_medium_monday">Mo.</string>
-    <string name="day_of_week_medium_tuesday">Di.</string>
-    <string name="day_of_week_medium_wednesday">Mi.</string>
-    <string name="day_of_week_medium_thursday">Do.</string>
-    <string name="day_of_week_medium_friday">Fr.</string>
-    <string name="day_of_week_medium_saturday">Sa.</string>
-
-    <string name="day_of_week_short_sunday">So.</string>
-    <string name="day_of_week_short_monday">Mo.</string>
-    <string name="day_of_week_short_tuesday">Di.</string>
-    <string name="day_of_week_short_wednesday">Mi.</string>
-    <string name="day_of_week_short_thursday">Do.</string>
-    <string name="day_of_week_short_friday">Fr.</string>
-    <string name="day_of_week_short_saturday">Sa.</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">D</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">D</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">vorm.</string>
-    <string name="pm">nachm.</string>
-    <string name="yesterday">Gestern</string>
-    <string name="today">Heute</string>
-    <string name="tomorrow">Morgen</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d.%m.%Y</string>
-    <string name="numeric_date_format">dd.MM.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
-    <string name="month_day_year">%-e. %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d.%m.%Y</string>
-    <string name="month_day">%-e. %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e. %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-de-rDE/donottranslate-cldr.xml b/core/res/res/values-de-rDE/donottranslate-cldr.xml
deleted file mode 100644
index f32095b..0000000
--- a/core/res/res/values-de-rDE/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Januar</string>
-    <string name="month_long_standalone_february">Februar</string>
-    <string name="month_long_standalone_march">März</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">Mai</string>
-    <string name="month_long_standalone_june">Juni</string>
-    <string name="month_long_standalone_july">Juli</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">Oktober</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">Dezember</string>
-
-    <string name="month_long_january">Januar</string>
-    <string name="month_long_february">Februar</string>
-    <string name="month_long_march">März</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">Mai</string>
-    <string name="month_long_june">Juni</string>
-    <string name="month_long_july">Juli</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">Oktober</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">Dezember</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mär</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mai</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dez</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sonntag</string>
-    <string name="day_of_week_long_monday">Montag</string>
-    <string name="day_of_week_long_tuesday">Dienstag</string>
-    <string name="day_of_week_long_wednesday">Mittwoch</string>
-    <string name="day_of_week_long_thursday">Donnerstag</string>
-    <string name="day_of_week_long_friday">Freitag</string>
-    <string name="day_of_week_long_saturday">Samstag</string>
-
-    <string name="day_of_week_medium_sunday">So.</string>
-    <string name="day_of_week_medium_monday">Mo.</string>
-    <string name="day_of_week_medium_tuesday">Di.</string>
-    <string name="day_of_week_medium_wednesday">Mi.</string>
-    <string name="day_of_week_medium_thursday">Do.</string>
-    <string name="day_of_week_medium_friday">Fr.</string>
-    <string name="day_of_week_medium_saturday">Sa.</string>
-
-    <string name="day_of_week_short_sunday">So.</string>
-    <string name="day_of_week_short_monday">Mo.</string>
-    <string name="day_of_week_short_tuesday">Di.</string>
-    <string name="day_of_week_short_wednesday">Mi.</string>
-    <string name="day_of_week_short_thursday">Do.</string>
-    <string name="day_of_week_short_friday">Fr.</string>
-    <string name="day_of_week_short_saturday">Sa.</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">D</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">D</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">vorm.</string>
-    <string name="pm">nachm.</string>
-    <string name="yesterday">Gestern</string>
-    <string name="today">Heute</string>
-    <string name="tomorrow">Morgen</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d.%m.%Y</string>
-    <string name="numeric_date_format">dd.MM.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
-    <string name="month_day_year">%-e. %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d.%m.%Y</string>
-    <string name="month_day">%-e. %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e. %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-de-rLI/donottranslate-cldr.xml b/core/res/res/values-de-rLI/donottranslate-cldr.xml
deleted file mode 100644
index f32095b..0000000
--- a/core/res/res/values-de-rLI/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Januar</string>
-    <string name="month_long_standalone_february">Februar</string>
-    <string name="month_long_standalone_march">März</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">Mai</string>
-    <string name="month_long_standalone_june">Juni</string>
-    <string name="month_long_standalone_july">Juli</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">Oktober</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">Dezember</string>
-
-    <string name="month_long_january">Januar</string>
-    <string name="month_long_february">Februar</string>
-    <string name="month_long_march">März</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">Mai</string>
-    <string name="month_long_june">Juni</string>
-    <string name="month_long_july">Juli</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">Oktober</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">Dezember</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mär</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mai</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dez</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sonntag</string>
-    <string name="day_of_week_long_monday">Montag</string>
-    <string name="day_of_week_long_tuesday">Dienstag</string>
-    <string name="day_of_week_long_wednesday">Mittwoch</string>
-    <string name="day_of_week_long_thursday">Donnerstag</string>
-    <string name="day_of_week_long_friday">Freitag</string>
-    <string name="day_of_week_long_saturday">Samstag</string>
-
-    <string name="day_of_week_medium_sunday">So.</string>
-    <string name="day_of_week_medium_monday">Mo.</string>
-    <string name="day_of_week_medium_tuesday">Di.</string>
-    <string name="day_of_week_medium_wednesday">Mi.</string>
-    <string name="day_of_week_medium_thursday">Do.</string>
-    <string name="day_of_week_medium_friday">Fr.</string>
-    <string name="day_of_week_medium_saturday">Sa.</string>
-
-    <string name="day_of_week_short_sunday">So.</string>
-    <string name="day_of_week_short_monday">Mo.</string>
-    <string name="day_of_week_short_tuesday">Di.</string>
-    <string name="day_of_week_short_wednesday">Mi.</string>
-    <string name="day_of_week_short_thursday">Do.</string>
-    <string name="day_of_week_short_friday">Fr.</string>
-    <string name="day_of_week_short_saturday">Sa.</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">D</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">D</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">vorm.</string>
-    <string name="pm">nachm.</string>
-    <string name="yesterday">Gestern</string>
-    <string name="today">Heute</string>
-    <string name="tomorrow">Morgen</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d.%m.%Y</string>
-    <string name="numeric_date_format">dd.MM.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
-    <string name="month_day_year">%-e. %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d.%m.%Y</string>
-    <string name="month_day">%-e. %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e. %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-de/donottranslate-cldr.xml b/core/res/res/values-de/donottranslate-cldr.xml
index f32095b..babf1a0 100644
--- a/core/res/res/values-de/donottranslate-cldr.xml
+++ b/core/res/res/values-de/donottranslate-cldr.xml
@@ -27,18 +27,18 @@
     <string name="month_long_november">November</string>
     <string name="month_long_december">Dezember</string>
 
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mär</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mai</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dez</string>
+    <string name="month_medium_january">Jan.</string>
+    <string name="month_medium_february">Feb.</string>
+    <string name="month_medium_march">Mär.</string>
+    <string name="month_medium_april">Apr.</string>
+    <string name="month_medium_may">Mai.</string>
+    <string name="month_medium_june">Jun.</string>
+    <string name="month_medium_july">Jul.</string>
+    <string name="month_medium_august">Aug.</string>
+    <string name="month_medium_september">Sep.</string>
+    <string name="month_medium_october">Okt.</string>
+    <string name="month_medium_november">Nov.</string>
+    <string name="month_medium_december">Dez.</string>
 
     <string name="month_shortest_january">J</string>
     <string name="month_shortest_february">F</string>
@@ -91,19 +91,19 @@
     <string name="today">Heute</string>
     <string name="tomorrow">Morgen</string>
 
-    <string name="hour_minute_24">%-k:%M</string>
+    <string name="hour_minute_24">%-k:%M h</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
     <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
+    <string name="twenty_four_hour_time_format">H:mm \'h\'</string>
     <string name="numeric_date">%d.%m.%Y</string>
     <string name="numeric_date_format">dd.MM.yyyy</string>
     <string name="numeric_date_template">"%s.%s.%s"</string>
     <string name="month_day_year">%-e. %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
+    <string name="time_of_day">%H:%M:%S h</string>
+    <string name="date_and_time">%d.%m.%Y, %H:%M:%S h</string>
+    <string name="date_time">%1$s, %2$s</string>
+    <string name="time_date">%3$s, %1$s</string>
     <string name="abbrev_month_day_year">%d.%m.%Y</string>
     <string name="month_day">%-e. %B</string>
     <string name="month">%-B</string>
@@ -111,37 +111,37 @@
     <string name="abbrev_month_day">%-e. %b</string>
     <string name="abbrev_month">%-b</string>
     <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
+    <string name="time1_time2">%1$s bis %2$s</string>
+    <string name="date1_date2">%2$s bis %5$s</string>
+    <string name="numeric_md1_md2">%3$s.%2$s. bis %8$s.%7$s.</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. bis %6$s, %8$s.%7$s.</string>
+    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s bis %8$s.%7$s.%9$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s bis %6$s, %8$s.%7$s.%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s.%2$s.%4$s, %5$s bis %6$s, %8$s.%7$s.%9$s, %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%3$s.%2$s., %5$s bis %8$s.%7$s., %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s.%2$s., %5$s bis %6$s, %8$s.%7$s., %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%3$s.%2$s.%4$s, %5$s bis %8$s.%7$s.%9$s, %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s bis %4$s, %5$s, %6$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s bis %4$s, %5$s</string>
+    <string name="date1_time1_date2_time2">%2$s, %3$s bis %5$s, %6$s</string>
+    <string name="time_wday_date">%2$s, %3$s, %1$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday">%2$s, %1$s</string>
+    <string name="same_year_md1_md2">%3$s. %2$s bis %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s bis %6$s, %8$s. %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%3$s. %2$s, %5$s bis %8$s. %7$s, %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%3$s. %2$s, %5$s bis %8$s. %7$s, %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s. %2$s, %5$s bis %6$s, %8$s. %7$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s. %2$s, %5$s bis %6$s, %8$s. %7$s, %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%3$s. %2$s %4$s, %5$s bis %8$s. %7$s %9$s, %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%3$s. %2$s %4$s, %5$s bis %8$s. %7$s %9$s, %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s. %2$s %4$s, %5$s bis %6$s, %8$s. %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s. %2$s %4$s, %5$s bis %6$s, %8$s. %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s bis %6$s, %8$s. %7$s %9$s</string>
+    <string name="same_month_md1_md2">%3$s. bis %8$s. %2$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s bis %6$s, %8$s. %7$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s. %2$s bis %8$s. %7$s %9$s</string>
+    <string name="same_month_mdy1_mdy2">%3$s. bis %8$s. %2$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s bis %6$s, %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 51de385..9163c61 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"Auf die Datei konnte nicht zugegriffen werden."</string>
     <string name="httpErrorFileNotFound">"Die angeforderte Datei wurde nicht gefunden."</string>
     <string name="httpErrorTooManyRequests">"Es werden zurzeit zu viele Anfragen verarbeitet. Versuchen Sie es später erneut."</string>
-    <string name="certificateSaved">"Das Zertifikat wird im Schlüsselspeicher des Systems gespeichert."</string>
     <string name="contentServiceSync">"Synchronisieren"</string>
     <string name="contentServiceSyncNotificationTitle">"Synchronisieren"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Zu viele <xliff:g id="CONTENT_TYPE">%s</xliff:g> gelöscht."</string>
diff --git a/core/res/res/values-el-rGR/donottranslate-cldr.xml b/core/res/res/values-el-rGR/donottranslate-cldr.xml
deleted file mode 100644
index e8f02fb..0000000
--- a/core/res/res/values-el-rGR/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Ιανουάριος</string>
-    <string name="month_long_standalone_february">Φεβρουάριος</string>
-    <string name="month_long_standalone_march">Μάρτιος</string>
-    <string name="month_long_standalone_april">Απρίλιος</string>
-    <string name="month_long_standalone_may">Μάιος</string>
-    <string name="month_long_standalone_june">Ιούνιος</string>
-    <string name="month_long_standalone_july">Ιούλιος</string>
-    <string name="month_long_standalone_august">Αύγουστος</string>
-    <string name="month_long_standalone_september">Σεπτέμβριος</string>
-    <string name="month_long_standalone_october">Οκτώβριος</string>
-    <string name="month_long_standalone_november">Νοέμβριος</string>
-    <string name="month_long_standalone_december">Δεκέμβριος</string>
-
-    <string name="month_long_january">Ιανουαρίου</string>
-    <string name="month_long_february">Φεβρουαρίου</string>
-    <string name="month_long_march">Μαρτίου</string>
-    <string name="month_long_april">Απριλίου</string>
-    <string name="month_long_may">Μαΐου</string>
-    <string name="month_long_june">Ιουνίου</string>
-    <string name="month_long_july">Ιουλίου</string>
-    <string name="month_long_august">Αυγούστου</string>
-    <string name="month_long_september">Σεπτεμβρίου</string>
-    <string name="month_long_october">Οκτωβρίου</string>
-    <string name="month_long_november">Νοεμβρίου</string>
-    <string name="month_long_december">Δεκεμβρίου</string>
-
-    <string name="month_medium_january">Ιαν</string>
-    <string name="month_medium_february">Φεβ</string>
-    <string name="month_medium_march">Μαρ</string>
-    <string name="month_medium_april">Απρ</string>
-    <string name="month_medium_may">Μαϊ</string>
-    <string name="month_medium_june">Ιουν</string>
-    <string name="month_medium_july">Ιουλ</string>
-    <string name="month_medium_august">Αυγ</string>
-    <string name="month_medium_september">Σεπ</string>
-    <string name="month_medium_october">Οκτ</string>
-    <string name="month_medium_november">Νοε</string>
-    <string name="month_medium_december">Δεκ</string>
-
-    <string name="month_shortest_january">Ι</string>
-    <string name="month_shortest_february">Φ</string>
-    <string name="month_shortest_march">Μ</string>
-    <string name="month_shortest_april">Α</string>
-    <string name="month_shortest_may">Μ</string>
-    <string name="month_shortest_june">Ι</string>
-    <string name="month_shortest_july">Ι</string>
-    <string name="month_shortest_august">Α</string>
-    <string name="month_shortest_september">Σ</string>
-    <string name="month_shortest_october">Ο</string>
-    <string name="month_shortest_november">Ν</string>
-    <string name="month_shortest_december">Δ</string>
-
-    <string name="day_of_week_long_sunday">Κυριακή</string>
-    <string name="day_of_week_long_monday">Δευτέρα</string>
-    <string name="day_of_week_long_tuesday">Τρίτη</string>
-    <string name="day_of_week_long_wednesday">Τετάρτη</string>
-    <string name="day_of_week_long_thursday">Πέμπτη</string>
-    <string name="day_of_week_long_friday">Παρασκευή</string>
-    <string name="day_of_week_long_saturday">Σάββατο</string>
-
-    <string name="day_of_week_medium_sunday">Κυρ</string>
-    <string name="day_of_week_medium_monday">Δευ</string>
-    <string name="day_of_week_medium_tuesday">Τρι</string>
-    <string name="day_of_week_medium_wednesday">Τετ</string>
-    <string name="day_of_week_medium_thursday">Πεμ</string>
-    <string name="day_of_week_medium_friday">Παρ</string>
-    <string name="day_of_week_medium_saturday">Σαβ</string>
-
-    <string name="day_of_week_short_sunday">Κυρ</string>
-    <string name="day_of_week_short_monday">Δευ</string>
-    <string name="day_of_week_short_tuesday">Τρι</string>
-    <string name="day_of_week_short_wednesday">Τετ</string>
-    <string name="day_of_week_short_thursday">Πεμ</string>
-    <string name="day_of_week_short_friday">Παρ</string>
-    <string name="day_of_week_short_saturday">Σαβ</string>
-
-    <string name="day_of_week_shortest_sunday">Κ</string>
-    <string name="day_of_week_shortest_monday">Δ</string>
-    <string name="day_of_week_shortest_tuesday">Τ</string>
-    <string name="day_of_week_shortest_wednesday">Τ</string>
-    <string name="day_of_week_shortest_thursday">Π</string>
-    <string name="day_of_week_shortest_friday">Π</string>
-    <string name="day_of_week_shortest_saturday">Σ</string>
-
-    <string name="am">π.μ.</string>
-    <string name="pm">μ.μ.</string>
-    <string name="yesterday">Χτες</string>
-    <string name="today">Σήμερα</string>
-    <string name="tomorrow">Αύριο</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d/%m/%Y</string>
-    <string name="numeric_date_format">dd/MM/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%d %B %Y</string>
-    <string name="time_of_day">%-l:%M:%S %p</string>
-    <string name="date_and_time">%-l:%M:%S %p %d %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d %b %Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%-B %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s/%2$s - %6$s, %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s/%2$s/%4$s - %6$s, %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s/%2$s/%4$s - %10$s %6$s, %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s/%2$s - %10$s %6$s, %8$s/%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s - %10$s %6$s, %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s - %10$s %6$s, %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 723ab03..3158a37 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Η πρόσβαση στο αρχείο δεν ήταν δυνατή."</string>
     <string name="httpErrorFileNotFound">"Το αρχείο που ζητήθηκε δεν βρέθηκε."</string>
     <string name="httpErrorTooManyRequests">"Πραγματοποιείται επεξεργασία πάρα πολλών αιτημάτων. Προσπαθήστε ξανά αργότερα."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Συγχρονισμός"</string>
     <string name="contentServiceSyncNotificationTitle">"Συγχρονισμός"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Πάρα πολλές <xliff:g id="CONTENT_TYPE">%s</xliff:g> διαγραφές."</string>
diff --git a/core/res/res/values-en-rGB/donottranslate-cldr.xml b/core/res/res/values-en-rGB/donottranslate-cldr.xml
index 0e3e035..65545ba 100644
--- a/core/res/res/values-en-rGB/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rGB/donottranslate-cldr.xml
@@ -121,25 +121,25 @@
     <string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s/%2$s, %5$s - %6$s, %8$s/%7$s, %10$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s, %3$s - %4$s %5$s, %6$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
     <string name="date1_time1_date2_time2">%2$s, %3$s - %5$s, %6$s</string>
-    <string name="time_wday_date">%1$s, %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday_date">%1$s, %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
     <string name="time_wday">%1$s, %2$s</string>
     <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
     <string name="same_month_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s - %6$s, %8$s %7$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s - %6$s, %8$s %7$s, %10$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rSG/donottranslate-cldr.xml b/core/res/res/values-en-rSG/donottranslate-cldr.xml
deleted file mode 100644
index 286cc0e..0000000
--- a/core/res/res/values-en-rSG/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">January</string>
-    <string name="month_long_standalone_february">February</string>
-    <string name="month_long_standalone_march">March</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">May</string>
-    <string name="month_long_standalone_june">June</string>
-    <string name="month_long_standalone_july">July</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">October</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">December</string>
-
-    <string name="month_long_january">January</string>
-    <string name="month_long_february">February</string>
-    <string name="month_long_march">March</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">May</string>
-    <string name="month_long_june">June</string>
-    <string name="month_long_july">July</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">October</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">December</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Oct</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sunday</string>
-    <string name="day_of_week_long_monday">Monday</string>
-    <string name="day_of_week_long_tuesday">Tuesday</string>
-    <string name="day_of_week_long_wednesday">Wednesday</string>
-    <string name="day_of_week_long_thursday">Thursday</string>
-    <string name="day_of_week_long_friday">Friday</string>
-    <string name="day_of_week_long_saturday">Saturday</string>
-
-    <string name="day_of_week_medium_sunday">Sun</string>
-    <string name="day_of_week_medium_monday">Mon</string>
-    <string name="day_of_week_medium_tuesday">Tue</string>
-    <string name="day_of_week_medium_wednesday">Wed</string>
-    <string name="day_of_week_medium_thursday">Thu</string>
-    <string name="day_of_week_medium_friday">Fri</string>
-    <string name="day_of_week_medium_saturday">Sat</string>
-
-    <string name="day_of_week_short_sunday">Su</string>
-    <string name="day_of_week_short_monday">Mo</string>
-    <string name="day_of_week_short_tuesday">Tu</string>
-    <string name="day_of_week_short_wednesday">We</string>
-    <string name="day_of_week_short_thursday">Th</string>
-    <string name="day_of_week_short_friday">Fr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">am</string>
-    <string name="pm">pm</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
-    <string name="hour_minute_24">%H:%M</string>
-    <string name="hour_minute_ampm">%-l:%M%p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">HH:mm</string>
-    <string name="numeric_date">%-m/%-e/%Y</string>
-    <string name="numeric_date_format">M/d/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%B %-e, %Y</string>
-    <string name="time_of_day">%-l:%M:%S %p</string>
-    <string name="date_and_time">%b %-e, %Y, %-l:%M:%S %p</string>
-    <string name="date_time">%1$s, %2$s</string>
-    <string name="time_date">%1$s, %3$s</string>
-    <string name="abbrev_month_day_year">%b %-e, %Y</string>
-    <string name="month_day">%B %-e</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s – %2$s</string>
-    <string name="date1_date2">%2$s – %5$s</string>
-    <string name="numeric_md1_md2">%2$s/%3$s – %7$s/%8$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s/%3$s – %6$s, %7$s/%8$s</string>
-    <string name="numeric_mdy1_mdy2">%2$s/%3$s/%4$s – %7$s/%8$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %2$s/%3$s/%4$s – %6$s, %7$s/%8$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s – %6$s, %7$s/%8$s/%9$s, %10$s</string>
-    <string name="numeric_md1_time1_md2_time2">%2$s/%3$s, %5$s – %7$s/%8$s, %10$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s – %6$s, %7$s/%8$s, %10$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%2$s/%3$s/%4$s, %5$s – %7$s/%8$s/%9$s, %10$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s – %4$s, %5$s, %6$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s – %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">%2$s, %3$s – %5$s, %6$s</string>
-    <string name="time_wday_date">%1$s, %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
-    <string name="time_wday">%1$s, %2$s</string>
-    <string name="same_year_md1_md2">%2$s %3$s – %7$s %8$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s – %6$s, %7$s %8$s</string>
-    <string name="same_year_md1_time1_md2_time2">%2$s %3$s, %5$s – %7$s %8$s, %10$s</string>
-    <string name="same_month_md1_time1_md2_time2">%2$s %3$s, %5$s – %7$s %8$s, %10$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s – %6$s, %7$s %8$s, %10$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s – %6$s, %7$s %8$s, %10$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s – %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s – %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s – %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s – %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s – %6$s, %7$s %8$s, %9$s</string>
-    <string name="same_month_md1_md2">%2$s %3$s – %8$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s – %6$s, %7$s %8$s</string>
-    <string name="same_year_mdy1_mdy2">%2$s %3$s – %7$s %8$s, %9$s</string>
-    <string name="same_month_mdy1_mdy2">%2$s %3$s – %8$s, %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s – %6$s, %7$s %8$s, %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-es-rES/donottranslate-cldr.xml b/core/res/res/values-es-rES/donottranslate-cldr.xml
deleted file mode 100644
index c1dc58b..0000000
--- a/core/res/res/values-es-rES/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">enero</string>
-    <string name="month_long_standalone_february">febrero</string>
-    <string name="month_long_standalone_march">marzo</string>
-    <string name="month_long_standalone_april">abril</string>
-    <string name="month_long_standalone_may">mayo</string>
-    <string name="month_long_standalone_june">junio</string>
-    <string name="month_long_standalone_july">julio</string>
-    <string name="month_long_standalone_august">agosto</string>
-    <string name="month_long_standalone_september">septiembre</string>
-    <string name="month_long_standalone_october">octubre</string>
-    <string name="month_long_standalone_november">noviembre</string>
-    <string name="month_long_standalone_december">diciembre</string>
-
-    <string name="month_long_january">enero</string>
-    <string name="month_long_february">febrero</string>
-    <string name="month_long_march">marzo</string>
-    <string name="month_long_april">abril</string>
-    <string name="month_long_may">mayo</string>
-    <string name="month_long_june">junio</string>
-    <string name="month_long_july">julio</string>
-    <string name="month_long_august">agosto</string>
-    <string name="month_long_september">septiembre</string>
-    <string name="month_long_october">octubre</string>
-    <string name="month_long_november">noviembre</string>
-    <string name="month_long_december">diciembre</string>
-
-    <string name="month_medium_january">ene</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">abr</string>
-    <string name="month_medium_may">may</string>
-    <string name="month_medium_june">jun</string>
-    <string name="month_medium_july">jul</string>
-    <string name="month_medium_august">ago</string>
-    <string name="month_medium_september">sep</string>
-    <string name="month_medium_october">oct</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dic</string>
-
-    <string name="month_shortest_january">E</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">domingo</string>
-    <string name="day_of_week_long_monday">lunes</string>
-    <string name="day_of_week_long_tuesday">martes</string>
-    <string name="day_of_week_long_wednesday">miércoles</string>
-    <string name="day_of_week_long_thursday">jueves</string>
-    <string name="day_of_week_long_friday">viernes</string>
-    <string name="day_of_week_long_saturday">sábado</string>
-
-    <string name="day_of_week_medium_sunday">dom</string>
-    <string name="day_of_week_medium_monday">lun</string>
-    <string name="day_of_week_medium_tuesday">mar</string>
-    <string name="day_of_week_medium_wednesday">mié</string>
-    <string name="day_of_week_medium_thursday">jue</string>
-    <string name="day_of_week_medium_friday">vie</string>
-    <string name="day_of_week_medium_saturday">sáb</string>
-
-    <string name="day_of_week_short_sunday">dom</string>
-    <string name="day_of_week_short_monday">lun</string>
-    <string name="day_of_week_short_tuesday">mar</string>
-    <string name="day_of_week_short_wednesday">mié</string>
-    <string name="day_of_week_short_thursday">jue</string>
-    <string name="day_of_week_short_friday">vie</string>
-    <string name="day_of_week_short_saturday">sáb</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">J</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">a.m.</string>
-    <string name="pm">p.m.</string>
-    <string name="yesterday">ayer</string>
-    <string name="today">hoy</string>
-    <string name="tomorrow">mañana</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d/%m/%Y</string>
-    <string name="numeric_date_format">dd/MM/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e de %B de %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d/%m/%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d/%m/%Y</string>
-    <string name="month_day">%-e de %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B de %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s – %2$s</string>
-    <string name="date1_date2">%2$s – %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s – %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s – %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s – %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s – %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s – %10$s %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s – %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s-%2$s – %10$s %6$s, %8$s-%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s – %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s de %2$s – %8$s de %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s – %10$s %8$s de %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s – %10$s %8$s de %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s – %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s–%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s – %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s – %6$s %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-es-rUS/donottranslate-cldr.xml b/core/res/res/values-es-rUS/donottranslate-cldr.xml
index d6d8954..7ade142 100644
--- a/core/res/res/values-es-rUS/donottranslate-cldr.xml
+++ b/core/res/res/values-es-rUS/donottranslate-cldr.xml
@@ -27,18 +27,18 @@
     <string name="month_long_november">noviembre</string>
     <string name="month_long_december">diciembre</string>
 
-    <string name="month_medium_january">ene</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">abr</string>
-    <string name="month_medium_may">may</string>
-    <string name="month_medium_june">jun</string>
-    <string name="month_medium_july">jul</string>
-    <string name="month_medium_august">ago</string>
-    <string name="month_medium_september">sep</string>
-    <string name="month_medium_october">oct</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dic</string>
+    <string name="month_medium_january">ene.</string>
+    <string name="month_medium_february">feb.</string>
+    <string name="month_medium_march">mar.</string>
+    <string name="month_medium_april">abr.</string>
+    <string name="month_medium_may">may.</string>
+    <string name="month_medium_june">jun.</string>
+    <string name="month_medium_july">jul.</string>
+    <string name="month_medium_august">ago.</string>
+    <string name="month_medium_september">sep.</string>
+    <string name="month_medium_october">oct.</string>
+    <string name="month_medium_november">nov.</string>
+    <string name="month_medium_december">dic.</string>
 
     <string name="month_shortest_january">E</string>
     <string name="month_shortest_february">F</string>
@@ -61,21 +61,21 @@
     <string name="day_of_week_long_friday">viernes</string>
     <string name="day_of_week_long_saturday">sábado</string>
 
-    <string name="day_of_week_medium_sunday">dom</string>
-    <string name="day_of_week_medium_monday">lun</string>
-    <string name="day_of_week_medium_tuesday">mar</string>
-    <string name="day_of_week_medium_wednesday">mié</string>
-    <string name="day_of_week_medium_thursday">jue</string>
-    <string name="day_of_week_medium_friday">vie</string>
-    <string name="day_of_week_medium_saturday">sáb</string>
+    <string name="day_of_week_medium_sunday">dom.</string>
+    <string name="day_of_week_medium_monday">lun.</string>
+    <string name="day_of_week_medium_tuesday">mar.</string>
+    <string name="day_of_week_medium_wednesday">mié.</string>
+    <string name="day_of_week_medium_thursday">jue.</string>
+    <string name="day_of_week_medium_friday">vie.</string>
+    <string name="day_of_week_medium_saturday">sáb.</string>
 
-    <string name="day_of_week_short_sunday">dom</string>
-    <string name="day_of_week_short_monday">lun</string>
-    <string name="day_of_week_short_tuesday">mar</string>
-    <string name="day_of_week_short_wednesday">mié</string>
-    <string name="day_of_week_short_thursday">jue</string>
-    <string name="day_of_week_short_friday">vie</string>
-    <string name="day_of_week_short_saturday">sáb</string>
+    <string name="day_of_week_short_sunday">dom.</string>
+    <string name="day_of_week_short_monday">lun.</string>
+    <string name="day_of_week_short_tuesday">mar.</string>
+    <string name="day_of_week_short_wednesday">mié.</string>
+    <string name="day_of_week_short_thursday">jue.</string>
+    <string name="day_of_week_short_friday">vie.</string>
+    <string name="day_of_week_short_saturday">sáb.</string>
 
     <string name="day_of_week_shortest_sunday">D</string>
     <string name="day_of_week_shortest_monday">L</string>
@@ -85,8 +85,8 @@
     <string name="day_of_week_shortest_friday">V</string>
     <string name="day_of_week_shortest_saturday">S</string>
 
-    <string name="am">a.m.</string>
-    <string name="pm">p.m.</string>
+    <string name="am">a. m.</string>
+    <string name="pm">p. m.</string>
     <string name="yesterday">ayer</string>
     <string name="today">hoy</string>
     <string name="tomorrow">mañana</string>
@@ -111,7 +111,7 @@
     <string name="abbrev_month_day">%-e de %b</string>
     <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b de %Y</string>
-    <string name="time1_time2">%1$s a el %2$s</string>
+    <string name="time1_time2">%1$s a %2$s</string>
     <string name="date1_date2">%2$s a el %5$s</string>
     <string name="numeric_md1_md2">%2$s/%3$s - %7$s/%8$s</string>
     <string name="numeric_wday1_md1_wday2_md2">%1$s %2$s/%3$s - %6$s %7$s/%8$s</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index d127f9c..ee28403 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"No se ha podido acceder al archivo."</string>
     <string name="httpErrorFileNotFound">"No se ha encontrado el archivo solicitado."</string>
     <string name="httpErrorTooManyRequests">"Se están procesando demasiadas solicitudes. Vuelve a intentarlo más tarde."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Sincronización"</string>
     <string name="contentServiceSyncNotificationTitle">"Sincronización"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Demasiadas eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g>"</string>
diff --git a/core/res/res/values-es/donottranslate-cldr.xml b/core/res/res/values-es/donottranslate-cldr.xml
index c1dc58b..0de0b64 100644
--- a/core/res/res/values-es/donottranslate-cldr.xml
+++ b/core/res/res/values-es/donottranslate-cldr.xml
@@ -27,18 +27,18 @@
     <string name="month_long_november">noviembre</string>
     <string name="month_long_december">diciembre</string>
 
-    <string name="month_medium_january">ene</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">abr</string>
-    <string name="month_medium_may">may</string>
-    <string name="month_medium_june">jun</string>
-    <string name="month_medium_july">jul</string>
-    <string name="month_medium_august">ago</string>
-    <string name="month_medium_september">sep</string>
-    <string name="month_medium_october">oct</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dic</string>
+    <string name="month_medium_january">ene.</string>
+    <string name="month_medium_february">feb.</string>
+    <string name="month_medium_march">mar.</string>
+    <string name="month_medium_april">abr.</string>
+    <string name="month_medium_may">may.</string>
+    <string name="month_medium_june">jun.</string>
+    <string name="month_medium_july">jul.</string>
+    <string name="month_medium_august">ago.</string>
+    <string name="month_medium_september">sep.</string>
+    <string name="month_medium_october">oct.</string>
+    <string name="month_medium_november">nov.</string>
+    <string name="month_medium_december">dic.</string>
 
     <string name="month_shortest_january">E</string>
     <string name="month_shortest_february">F</string>
@@ -61,21 +61,21 @@
     <string name="day_of_week_long_friday">viernes</string>
     <string name="day_of_week_long_saturday">sábado</string>
 
-    <string name="day_of_week_medium_sunday">dom</string>
-    <string name="day_of_week_medium_monday">lun</string>
-    <string name="day_of_week_medium_tuesday">mar</string>
-    <string name="day_of_week_medium_wednesday">mié</string>
-    <string name="day_of_week_medium_thursday">jue</string>
-    <string name="day_of_week_medium_friday">vie</string>
-    <string name="day_of_week_medium_saturday">sáb</string>
+    <string name="day_of_week_medium_sunday">dom.</string>
+    <string name="day_of_week_medium_monday">lun.</string>
+    <string name="day_of_week_medium_tuesday">mar.</string>
+    <string name="day_of_week_medium_wednesday">mié.</string>
+    <string name="day_of_week_medium_thursday">jue.</string>
+    <string name="day_of_week_medium_friday">vie.</string>
+    <string name="day_of_week_medium_saturday">sáb.</string>
 
-    <string name="day_of_week_short_sunday">dom</string>
-    <string name="day_of_week_short_monday">lun</string>
-    <string name="day_of_week_short_tuesday">mar</string>
-    <string name="day_of_week_short_wednesday">mié</string>
-    <string name="day_of_week_short_thursday">jue</string>
-    <string name="day_of_week_short_friday">vie</string>
-    <string name="day_of_week_short_saturday">sáb</string>
+    <string name="day_of_week_short_sunday">dom.</string>
+    <string name="day_of_week_short_monday">lun.</string>
+    <string name="day_of_week_short_tuesday">mar.</string>
+    <string name="day_of_week_short_wednesday">mié.</string>
+    <string name="day_of_week_short_thursday">jue.</string>
+    <string name="day_of_week_short_friday">vie.</string>
+    <string name="day_of_week_short_saturday">sáb.</string>
 
     <string name="day_of_week_shortest_sunday">D</string>
     <string name="day_of_week_shortest_monday">L</string>
@@ -101,47 +101,47 @@
     <string name="numeric_date_template">"%s/%s/%s"</string>
     <string name="month_day_year">%-e de %B de %Y</string>
     <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d/%m/%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
+    <string name="date_and_time">%d/%m/%Y, %H:%M:%S</string>
+    <string name="date_time">%1$s, %2$s</string>
+    <string name="time_date">%3$s, %1$s</string>
     <string name="abbrev_month_day_year">%d/%m/%Y</string>
     <string name="month_day">%-e de %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%B de %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
+    <string name="abbrev_month_day">%-e de %b</string>
     <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
+    <string name="abbrev_month_year">%b de %Y</string>
     <string name="time1_time2">%1$s – %2$s</string>
     <string name="date1_date2">%2$s – %5$s</string>
     <string name="numeric_md1_md2">%3$s/%2$s – %8$s/%7$s</string>
     <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s – %6$s %8$s/%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s – %8$s/%7$s/%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s – %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s – %10$s %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s – %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s-%2$s – %10$s %6$s, %8$s-%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s – %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s/%2$s/%4$s, %5$s – %6$s %8$s/%7$s/%9$s, %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s – %8$s/%7$s, %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s %3$s-%2$s, %5$s – %6$s %8$s-%7$s, %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s – %8$s/%7$s/%9$s, %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s, %3$s – %4$s %5$s, %6$s</string>
     <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
+    <string name="date1_time1_date2_time2">%2$s, %3$s – %5$s, %6$s</string>
+    <string name="time_wday_date">%2$s %3$s, %1$s</string>
     <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
+    <string name="time_wday">%2$s, %1$s</string>
     <string name="same_year_md1_md2">%3$s de %2$s – %8$s de %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s – %10$s %8$s de %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s – %10$s %8$s de %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s – %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s–%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s – %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s – %6$s %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s de %2$s – %6$s %8$s de %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%3$s de %2$s, %5$s – %8$s de %7$s, %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%3$s de %2$s, %5$s – %8$s de %7$s, %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s %3$s de %2$s, %5$s – %6$s %8$s de %7$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s de %2$s, %5$s – %6$s %8$s de %7$s, %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%3$s de %2$s de %4$s, %5$s – %8$s de %7$s de %9$s, %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%3$s de %2$s de %4$s, %5$s – %8$s de %7$s de %9$s, %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s de %2$s de %4$s, %5$s – %6$s %8$s de %7$s de %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s de %2$s de %4$s, %5$s – %6$s %8$s de %7$s de %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s de %4$s – %6$s %8$s de %7$s de %9$s</string>
+    <string name="same_month_md1_md2">%3$s–%8$s de %2$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s de %2$s – %6$s %8$s de %7$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s de %2$s – %8$s de %7$s de %9$s</string>
+    <string name="same_month_mdy1_mdy2">%3$s–%8$s de %2$s de %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s – %6$s %8$s de %7$s de %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 47bdd53..f3ff316 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"No se ha podido acceder al archivo."</string>
     <string name="httpErrorFileNotFound">"No se ha encontrado el archivo solicitado."</string>
     <string name="httpErrorTooManyRequests">"Se están procesando demasiadas solicitudes. Vuelve a intentarlo más tarde."</string>
-    <string name="certificateSaved">"El certificado se guarda en el almacén de claves del sistema."</string>
     <string name="contentServiceSync">"Sincronización"</string>
     <string name="contentServiceSyncNotificationTitle">"Sincronización"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Demasiadas eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g>"</string>
diff --git a/core/res/res/values-fi-rFI/donottranslate-cldr.xml b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
index df3866e..151d935 100644
--- a/core/res/res/values-fi-rFI/donottranslate-cldr.xml
+++ b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
@@ -53,13 +53,13 @@
     <string name="month_shortest_november">M</string>
     <string name="month_shortest_december">J</string>
 
-    <string name="day_of_week_long_sunday">sunnuntaina</string>
-    <string name="day_of_week_long_monday">maanantaina</string>
-    <string name="day_of_week_long_tuesday">tiistaina</string>
-    <string name="day_of_week_long_wednesday">keskiviikkona</string>
-    <string name="day_of_week_long_thursday">torstaina</string>
-    <string name="day_of_week_long_friday">perjantaina</string>
-    <string name="day_of_week_long_saturday">lauantaina</string>
+    <string name="day_of_week_long_sunday">sunnuntai</string>
+    <string name="day_of_week_long_monday">maanantai</string>
+    <string name="day_of_week_long_tuesday">tiistai</string>
+    <string name="day_of_week_long_wednesday">keskiviikko</string>
+    <string name="day_of_week_long_thursday">torstai</string>
+    <string name="day_of_week_long_friday">perjantai</string>
+    <string name="day_of_week_long_saturday">lauantai</string>
 
     <string name="day_of_week_medium_sunday">su</string>
     <string name="day_of_week_medium_monday">ma</string>
@@ -106,42 +106,42 @@
     <string name="time_date">%1$s %3$s</string>
     <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
     <string name="month_day">%-e. %B</string>
-    <string name="month">%-b</string>
+    <string name="month">%-B</string>
     <string name="month_year">%-B %Y</string>
-    <string name="abbrev_month_day">%-e. %b</string>
+    <string name="abbrev_month_day">%-e.%-m.</string>
     <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%-b %Y</string>
+    <string name="abbrev_month_year">%-B %Y</string>
     <string name="time1_time2">%1$s–%2$s</string>
-    <string name="date1_date2">%2$s–%5$s</string>
+    <string name="date1_date2">%2$s – %5$s</string>
     <string name="numeric_md1_md2">%3$s.%2$s.–%8$s.%7$s.</string>
     <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s.%2$s. – %6$s %8$s.%7$s.</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s–%8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s.%2$s.%4$s – %6$s %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s.%2$s.%4$s–%10$s %6$s %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s.–%10$s %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s.%2$s.–%10$s %6$s %8$s.%7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s–%10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s–%6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s–%4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s–%6$s %5$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s.%2$s.%4$s – %10$s %6$s %8$s.%7$s.%9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. – %10$s %8$s.%7$s.</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s.%2$s. – %10$s %6$s %8$s.%7$s.</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s – %10$s %8$s.%7$s.%9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
     <string name="time_wday_date">%1$s %2$s %3$s</string>
     <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s–%8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s–%6$s %8$s. %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s–%10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s–%10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s–%10$s %6$s %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s–%10$s %6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s–%10$s %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s–%10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s–%10$s %6$s %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s–%10$s %6$s %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s %4$s–%6$s %8$s. %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s.–%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s–%6$s %8$s. %7$s</string>
+    <string name="same_year_md1_md2">%3$s. %2$s – %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s – %6$s %8$s. %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s – %10$s %8$s. %7$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s – %10$s %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s – %10$s %6$s %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s – %10$s %6$s %8$s. %7$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s – %10$s %8$s. %7$s %9$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s – %10$s %8$s. %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s – %10$s %6$s %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s – %10$s %6$s %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s %4$s – %6$s %8$s. %7$s %9$s</string>
+    <string name="same_month_md1_md2">%3$s. – %8$s. %2$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s – %6$s %8$s. %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s. %2$s – %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s.–%8$s. %2$s %9$s</string>
+    <string name="same_month_mdy1_mdy2">%3$s. – %8$s. %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s – %6$s %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-fr-rBE/donottranslate-cldr.xml b/core/res/res/values-fr-rBE/donottranslate-cldr.xml
deleted file mode 100644
index e190837..0000000
--- a/core/res/res/values-fr-rBE/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">janvier</string>
-    <string name="month_long_standalone_february">février</string>
-    <string name="month_long_standalone_march">mars</string>
-    <string name="month_long_standalone_april">avril</string>
-    <string name="month_long_standalone_may">mai</string>
-    <string name="month_long_standalone_june">juin</string>
-    <string name="month_long_standalone_july">juillet</string>
-    <string name="month_long_standalone_august">août</string>
-    <string name="month_long_standalone_september">septembre</string>
-    <string name="month_long_standalone_october">octobre</string>
-    <string name="month_long_standalone_november">novembre</string>
-    <string name="month_long_standalone_december">décembre</string>
-
-    <string name="month_long_january">janvier</string>
-    <string name="month_long_february">février</string>
-    <string name="month_long_march">mars</string>
-    <string name="month_long_april">avril</string>
-    <string name="month_long_may">mai</string>
-    <string name="month_long_june">juin</string>
-    <string name="month_long_july">juillet</string>
-    <string name="month_long_august">août</string>
-    <string name="month_long_september">septembre</string>
-    <string name="month_long_october">octobre</string>
-    <string name="month_long_november">novembre</string>
-    <string name="month_long_december">décembre</string>
-
-    <string name="month_medium_january">janv.</string>
-    <string name="month_medium_february">févr.</string>
-    <string name="month_medium_march">mars</string>
-    <string name="month_medium_april">avr.</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">juin</string>
-    <string name="month_medium_july">juil.</string>
-    <string name="month_medium_august">août</string>
-    <string name="month_medium_september">sept.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">déc.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">dimanche</string>
-    <string name="day_of_week_long_monday">lundi</string>
-    <string name="day_of_week_long_tuesday">mardi</string>
-    <string name="day_of_week_long_wednesday">mercredi</string>
-    <string name="day_of_week_long_thursday">jeudi</string>
-    <string name="day_of_week_long_friday">vendredi</string>
-    <string name="day_of_week_long_saturday">samedi</string>
-
-    <string name="day_of_week_medium_sunday">dim.</string>
-    <string name="day_of_week_medium_monday">lun.</string>
-    <string name="day_of_week_medium_tuesday">mar.</string>
-    <string name="day_of_week_medium_wednesday">mer.</string>
-    <string name="day_of_week_medium_thursday">jeu.</string>
-    <string name="day_of_week_medium_friday">ven.</string>
-    <string name="day_of_week_medium_saturday">sam.</string>
-
-    <string name="day_of_week_short_sunday">dim.</string>
-    <string name="day_of_week_short_monday">lun.</string>
-    <string name="day_of_week_short_tuesday">mar.</string>
-    <string name="day_of_week_short_wednesday">mer.</string>
-    <string name="day_of_week_short_thursday">jeu.</string>
-    <string name="day_of_week_short_friday">ven.</string>
-    <string name="day_of_week_short_saturday">sam.</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">J</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">matin</string>
-    <string name="pm">soir</string>
-    <string name="yesterday">hier</string>
-    <string name="today">aujourd’hui</string>
-    <string name="tomorrow">demain</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%-e/%m/%Y</string>
-    <string name="numeric_date_format">d/MM/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e %b %Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">du %1$s au %2$s</string>
-    <string name="date1_date2">du %2$s au %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s %3$s/%2$s/%4$s au %10$s %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">du %5$s %3$s/%2$s au %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s %3$s/%2$s au %10$s %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">du %5$s %3$s/%2$s/%4$s au %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">du %3$s %1$s %2$s au %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">du %1$s %2$s au %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">du %3$s %2$s au %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">du %3$s %2$s au %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">du %1$s %3$s %2$s au %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">du %5$s %3$s %2$s au %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">du %5$s %3$s %2$s au %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s %3$s %2$s au %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s %3$s %2$s au %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">du %5$s %3$s %2$s %4$s au %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">du %5$s %3$s %2$s %4$s au %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s %3$s %2$s %4$s au %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s %3$s %2$s %4$s au %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">du %1$s %3$s %2$s %4$s au %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">du %1$s %3$s %2$s au %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s au %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s au %6$s %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-fr-rCA/donottranslate-cldr.xml b/core/res/res/values-fr-rCA/donottranslate-cldr.xml
deleted file mode 100644
index 346b971..0000000
--- a/core/res/res/values-fr-rCA/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">janvier</string>
-    <string name="month_long_standalone_february">février</string>
-    <string name="month_long_standalone_march">mars</string>
-    <string name="month_long_standalone_april">avril</string>
-    <string name="month_long_standalone_may">mai</string>
-    <string name="month_long_standalone_june">juin</string>
-    <string name="month_long_standalone_july">juillet</string>
-    <string name="month_long_standalone_august">août</string>
-    <string name="month_long_standalone_september">septembre</string>
-    <string name="month_long_standalone_october">octobre</string>
-    <string name="month_long_standalone_november">novembre</string>
-    <string name="month_long_standalone_december">décembre</string>
-
-    <string name="month_long_january">janvier</string>
-    <string name="month_long_february">février</string>
-    <string name="month_long_march">mars</string>
-    <string name="month_long_april">avril</string>
-    <string name="month_long_may">mai</string>
-    <string name="month_long_june">juin</string>
-    <string name="month_long_july">juillet</string>
-    <string name="month_long_august">août</string>
-    <string name="month_long_september">septembre</string>
-    <string name="month_long_october">octobre</string>
-    <string name="month_long_november">novembre</string>
-    <string name="month_long_december">décembre</string>
-
-    <string name="month_medium_january">janv.</string>
-    <string name="month_medium_february">févr.</string>
-    <string name="month_medium_march">mars</string>
-    <string name="month_medium_april">avr.</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">juin</string>
-    <string name="month_medium_july">juil.</string>
-    <string name="month_medium_august">août</string>
-    <string name="month_medium_september">sept.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">déc.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">dimanche</string>
-    <string name="day_of_week_long_monday">lundi</string>
-    <string name="day_of_week_long_tuesday">mardi</string>
-    <string name="day_of_week_long_wednesday">mercredi</string>
-    <string name="day_of_week_long_thursday">jeudi</string>
-    <string name="day_of_week_long_friday">vendredi</string>
-    <string name="day_of_week_long_saturday">samedi</string>
-
-    <string name="day_of_week_medium_sunday">dim.</string>
-    <string name="day_of_week_medium_monday">lun.</string>
-    <string name="day_of_week_medium_tuesday">mar.</string>
-    <string name="day_of_week_medium_wednesday">mer.</string>
-    <string name="day_of_week_medium_thursday">jeu.</string>
-    <string name="day_of_week_medium_friday">ven.</string>
-    <string name="day_of_week_medium_saturday">sam.</string>
-
-    <string name="day_of_week_short_sunday">dim.</string>
-    <string name="day_of_week_short_monday">lun.</string>
-    <string name="day_of_week_short_tuesday">mar.</string>
-    <string name="day_of_week_short_wednesday">mer.</string>
-    <string name="day_of_week_short_thursday">jeu.</string>
-    <string name="day_of_week_short_friday">ven.</string>
-    <string name="day_of_week_short_saturday">sam.</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">J</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">matin</string>
-    <string name="pm">soir</string>
-    <string name="yesterday">hier</string>
-    <string name="today">aujourd’hui</string>
-    <string name="tomorrow">demain</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%Y-%m-%d</string>
-    <string name="numeric_date_format">yyyy-MM-dd</string>
-    <string name="numeric_date_template">"%s-%s-%s"</string>
-    <string name="month_day_year">%-e %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %Y-%m-%d</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%Y-%m-%d</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s – %2$s</string>
-    <string name="date1_date2">%2$s – %5$s</string>
-    <string name="numeric_md1_md2">%2$s-%3$s – %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %2$s-%3$s – %6$s %7$s-%8$s</string>
-    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s – %9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">du %1$s %4$s-%2$s-%3$s au %6$s %9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %4$s-%2$s-%3$s – %10$s %6$s %9$s-%7$s-%8$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s – %10$s %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s-%3$s – %10$s %6$s %7$s-%8$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s – %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s – %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s – %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s – %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s–%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">du %3$s %2$s au %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">du %1$s %3$s %2$s au %6$s %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-fr-rCH/donottranslate-cldr.xml b/core/res/res/values-fr-rCH/donottranslate-cldr.xml
deleted file mode 100644
index 48db6b8..0000000
--- a/core/res/res/values-fr-rCH/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">janvier</string>
-    <string name="month_long_standalone_february">février</string>
-    <string name="month_long_standalone_march">mars</string>
-    <string name="month_long_standalone_april">avril</string>
-    <string name="month_long_standalone_may">mai</string>
-    <string name="month_long_standalone_june">juin</string>
-    <string name="month_long_standalone_july">juillet</string>
-    <string name="month_long_standalone_august">août</string>
-    <string name="month_long_standalone_september">septembre</string>
-    <string name="month_long_standalone_october">octobre</string>
-    <string name="month_long_standalone_november">novembre</string>
-    <string name="month_long_standalone_december">décembre</string>
-
-    <string name="month_long_january">janvier</string>
-    <string name="month_long_february">février</string>
-    <string name="month_long_march">mars</string>
-    <string name="month_long_april">avril</string>
-    <string name="month_long_may">mai</string>
-    <string name="month_long_june">juin</string>
-    <string name="month_long_july">juillet</string>
-    <string name="month_long_august">août</string>
-    <string name="month_long_september">septembre</string>
-    <string name="month_long_october">octobre</string>
-    <string name="month_long_november">novembre</string>
-    <string name="month_long_december">décembre</string>
-
-    <string name="month_medium_january">janv.</string>
-    <string name="month_medium_february">févr.</string>
-    <string name="month_medium_march">mars</string>
-    <string name="month_medium_april">avr.</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">juin</string>
-    <string name="month_medium_july">juil.</string>
-    <string name="month_medium_august">août</string>
-    <string name="month_medium_september">sept.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">déc.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">dimanche</string>
-    <string name="day_of_week_long_monday">lundi</string>
-    <string name="day_of_week_long_tuesday">mardi</string>
-    <string name="day_of_week_long_wednesday">mercredi</string>
-    <string name="day_of_week_long_thursday">jeudi</string>
-    <string name="day_of_week_long_friday">vendredi</string>
-    <string name="day_of_week_long_saturday">samedi</string>
-
-    <string name="day_of_week_medium_sunday">dim.</string>
-    <string name="day_of_week_medium_monday">lun.</string>
-    <string name="day_of_week_medium_tuesday">mar.</string>
-    <string name="day_of_week_medium_wednesday">mer.</string>
-    <string name="day_of_week_medium_thursday">jeu.</string>
-    <string name="day_of_week_medium_friday">ven.</string>
-    <string name="day_of_week_medium_saturday">sam.</string>
-
-    <string name="day_of_week_short_sunday">dim.</string>
-    <string name="day_of_week_short_monday">lun.</string>
-    <string name="day_of_week_short_tuesday">mar.</string>
-    <string name="day_of_week_short_wednesday">mer.</string>
-    <string name="day_of_week_short_thursday">jeu.</string>
-    <string name="day_of_week_short_friday">ven.</string>
-    <string name="day_of_week_short_saturday">sam.</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">J</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">matin</string>
-    <string name="pm">soir</string>
-    <string name="yesterday">hier</string>
-    <string name="today">aujourd’hui</string>
-    <string name="tomorrow">demain</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d.%m.%Y</string>
-    <string name="numeric_date_format">dd.MM.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
-    <string name="month_day_year">%-e %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e %b %Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">du %1$s au %2$s</string>
-    <string name="date1_date2">du %2$s au %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s, %3$s.%2$s.%4$s au %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">du %5$s %3$s.%2$s au %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s, %3$s.%2$s au %10$s %6$s, %8$s.%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">du %5$s %3$s.%2$s.%4$s au %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">du %3$s %1$s, %2$s au %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">du %1$s, %2$s au %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">du %3$s %2$s au %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">du %3$s %2$s au %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">du %1$s, %3$s %2$s au %6$s, %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">du %5$s %3$s %2$s au %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">du %5$s %3$s %2$s au %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s, %3$s %2$s au %10$s %6$s, %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s, %3$s %2$s au %10$s %6$s, %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">du %5$s %3$s %2$s %4$s au %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">du %5$s %3$s %2$s %4$s au %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s, %3$s %2$s %4$s au %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s, %3$s %2$s %4$s au %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">du %1$s, %3$s %2$s %4$s au %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">du %1$s, %3$s %2$s au %6$s, %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s au %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s au %6$s, %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-fr-rFR/donottranslate-cldr.xml b/core/res/res/values-fr-rFR/donottranslate-cldr.xml
deleted file mode 100644
index f340e83..0000000
--- a/core/res/res/values-fr-rFR/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">janvier</string>
-    <string name="month_long_standalone_february">février</string>
-    <string name="month_long_standalone_march">mars</string>
-    <string name="month_long_standalone_april">avril</string>
-    <string name="month_long_standalone_may">mai</string>
-    <string name="month_long_standalone_june">juin</string>
-    <string name="month_long_standalone_july">juillet</string>
-    <string name="month_long_standalone_august">août</string>
-    <string name="month_long_standalone_september">septembre</string>
-    <string name="month_long_standalone_october">octobre</string>
-    <string name="month_long_standalone_november">novembre</string>
-    <string name="month_long_standalone_december">décembre</string>
-
-    <string name="month_long_january">janvier</string>
-    <string name="month_long_february">février</string>
-    <string name="month_long_march">mars</string>
-    <string name="month_long_april">avril</string>
-    <string name="month_long_may">mai</string>
-    <string name="month_long_june">juin</string>
-    <string name="month_long_july">juillet</string>
-    <string name="month_long_august">août</string>
-    <string name="month_long_september">septembre</string>
-    <string name="month_long_october">octobre</string>
-    <string name="month_long_november">novembre</string>
-    <string name="month_long_december">décembre</string>
-
-    <string name="month_medium_january">janv.</string>
-    <string name="month_medium_february">févr.</string>
-    <string name="month_medium_march">mars</string>
-    <string name="month_medium_april">avr.</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">juin</string>
-    <string name="month_medium_july">juil.</string>
-    <string name="month_medium_august">août</string>
-    <string name="month_medium_september">sept.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">déc.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">dimanche</string>
-    <string name="day_of_week_long_monday">lundi</string>
-    <string name="day_of_week_long_tuesday">mardi</string>
-    <string name="day_of_week_long_wednesday">mercredi</string>
-    <string name="day_of_week_long_thursday">jeudi</string>
-    <string name="day_of_week_long_friday">vendredi</string>
-    <string name="day_of_week_long_saturday">samedi</string>
-
-    <string name="day_of_week_medium_sunday">dim.</string>
-    <string name="day_of_week_medium_monday">lun.</string>
-    <string name="day_of_week_medium_tuesday">mar.</string>
-    <string name="day_of_week_medium_wednesday">mer.</string>
-    <string name="day_of_week_medium_thursday">jeu.</string>
-    <string name="day_of_week_medium_friday">ven.</string>
-    <string name="day_of_week_medium_saturday">sam.</string>
-
-    <string name="day_of_week_short_sunday">dim.</string>
-    <string name="day_of_week_short_monday">lun.</string>
-    <string name="day_of_week_short_tuesday">mar.</string>
-    <string name="day_of_week_short_wednesday">mer.</string>
-    <string name="day_of_week_short_thursday">jeu.</string>
-    <string name="day_of_week_short_friday">ven.</string>
-    <string name="day_of_week_short_saturday">sam.</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">J</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">matin</string>
-    <string name="pm">soir</string>
-    <string name="yesterday">hier</string>
-    <string name="today">aujourd’hui</string>
-    <string name="tomorrow">demain</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d/%m/%Y</string>
-    <string name="numeric_date_format">dd/MM/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e %b %Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s – %2$s</string>
-    <string name="date1_date2">%2$s – %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s – %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s – %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s – %10$s %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s – %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s – %10$s %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s – %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s – %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s – %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s – %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s – %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s–%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s – %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s – %6$s %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-fr/donottranslate-cldr.xml b/core/res/res/values-fr/donottranslate-cldr.xml
index f340e83..bf93039 100644
--- a/core/res/res/values-fr/donottranslate-cldr.xml
+++ b/core/res/res/values-fr/donottranslate-cldr.xml
@@ -101,9 +101,9 @@
     <string name="numeric_date_template">"%s/%s/%s"</string>
     <string name="month_day_year">%-e %B %Y</string>
     <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
+    <string name="date_and_time">%-e %b %Y à %H:%M:%S</string>
+    <string name="date_time">%1$s à %2$s</string>
+    <string name="time_date">%3$s à %1$s</string>
     <string name="abbrev_month_day_year">%-e %b %Y</string>
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
@@ -111,37 +111,37 @@
     <string name="abbrev_month_day">%-e %b</string>
     <string name="abbrev_month">%-b</string>
     <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s – %2$s</string>
-    <string name="date1_date2">%2$s – %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s – %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s – %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s – %10$s %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s – %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s – %10$s %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s – %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
+    <string name="time1_time2">de %1$s à %2$s</string>
+    <string name="date1_date2">du %2$s au %5$s</string>
+    <string name="numeric_md1_md2">du %3$s/%2$s au %8$s/%7$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">du %1$s %3$s/%2$s au %6$s %8$s/%7$s</string>
+    <string name="numeric_mdy1_mdy2">du %3$s/%2$s/%4$s au %8$s/%7$s/%9$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">du %1$s %3$s/%2$s/%4$s au %6$s %8$s/%7$s/%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">du %1$s %3$s/%2$s/%4$s à %5$s au %6$s %8$s/%7$s/%9$s à %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">du %3$s/%2$s à %5$s au %8$s/%7$s à %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">du %1$s %3$s/%2$s à %5$s au %6$s %8$s/%7$s à %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">du %3$s/%2$s/%4$s à %5$s au %8$s/%7$s/%9$s à %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">du %1$s %2$s à %3$s au %4$s %5$s à %6$s</string>
+    <string name="wday1_date1_wday2_date2">du %1$s %2$s au %4$s %5$s</string>
+    <string name="date1_time1_date2_time2">du %2$s à %3$s au %5$s à %6$s</string>
+    <string name="time_wday_date">%2$s %3$s à %1$s</string>
     <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s – %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s – %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s – %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s – %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s–%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s – %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s – %6$s %8$s %7$s %9$s</string>
+    <string name="time_wday">%2$s à %1$s</string>
+    <string name="same_year_md1_md2">du %3$s %2$s au %8$s %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">du %1$s %3$s %2$s au %6$s %8$s %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">du %3$s %2$s à %5$s au %8$s %7$s à %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">du %3$s %2$s à %5$s au %8$s %7$s à %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">du %1$s %3$s %2$s à %5$s au %6$s %8$s %7$s à %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">du %1$s %3$s %2$s à %5$s au %6$s %8$s %7$s à %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">du %3$s %2$s %4$s à %5$s au %8$s %7$s %9$s à %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">du %3$s %2$s %4$s à %5$s au %8$s %7$s %9$s à %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">du %1$s %3$s %2$s %4$s à %5$s au %6$s %8$s %7$s %9$s à %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">du %1$s %3$s %2$s %4$s à %5$s au %6$s %8$s %7$s %9$s à %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">du %1$s %3$s %2$s %4$s au %6$s %8$s %7$s %9$s</string>
+    <string name="same_month_md1_md2">du %3$s au %8$s %2$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">du %1$s %3$s %2$s au %6$s %8$s %7$s</string>
+    <string name="same_year_mdy1_mdy2">du %3$s %2$s au %8$s %7$s %9$s</string>
+    <string name="same_month_mdy1_mdy2">du %3$s au %8$s %2$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">du %1$s %3$s %2$s au %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4c1af4c..ae3c807 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"Impossible d\'accéder au fichier."</string>
     <string name="httpErrorFileNotFound">"Le fichier demandé est introuvable."</string>
     <string name="httpErrorTooManyRequests">"Trop de requêtes sont en cours de traitement. Veuillez réessayer ultérieurement."</string>
-    <string name="certificateSaved">"Le certificat est enregistré dans le magasin de clés du système."</string>
     <string name="contentServiceSync">"Synchroniser"</string>
     <string name="contentServiceSyncNotificationTitle">"Synchronisation"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Trop de contenus supprimés (<xliff:g id="CONTENT_TYPE">%s</xliff:g>)."</string>
diff --git a/core/res/res/values-he-rIL/donottranslate-cldr.xml b/core/res/res/values-he-rIL/donottranslate-cldr.xml
deleted file mode 100644
index 3378ed7..0000000
--- a/core/res/res/values-he-rIL/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">ינואר</string>
-    <string name="month_long_standalone_february">פברואר</string>
-    <string name="month_long_standalone_march">מרס</string>
-    <string name="month_long_standalone_april">אפריל</string>
-    <string name="month_long_standalone_may">מאי</string>
-    <string name="month_long_standalone_june">יוני</string>
-    <string name="month_long_standalone_july">יולי</string>
-    <string name="month_long_standalone_august">אוגוסט</string>
-    <string name="month_long_standalone_september">ספטמבר</string>
-    <string name="month_long_standalone_october">אוקטובר</string>
-    <string name="month_long_standalone_november">נובמבר</string>
-    <string name="month_long_standalone_december">דצמבר</string>
-
-    <string name="month_long_january">ינואר</string>
-    <string name="month_long_february">פברואר</string>
-    <string name="month_long_march">מרס</string>
-    <string name="month_long_april">אפריל</string>
-    <string name="month_long_may">מאי</string>
-    <string name="month_long_june">יוני</string>
-    <string name="month_long_july">יולי</string>
-    <string name="month_long_august">אוגוסט</string>
-    <string name="month_long_september">ספטמבר</string>
-    <string name="month_long_october">אוקטובר</string>
-    <string name="month_long_november">נובמבר</string>
-    <string name="month_long_december">דצמבר</string>
-
-    <string name="month_medium_january">ינו</string>
-    <string name="month_medium_february">פבר</string>
-    <string name="month_medium_march">מרס</string>
-    <string name="month_medium_april">אפר</string>
-    <string name="month_medium_may">מאי</string>
-    <string name="month_medium_june">יונ</string>
-    <string name="month_medium_july">יול</string>
-    <string name="month_medium_august">אוג</string>
-    <string name="month_medium_september">ספט</string>
-    <string name="month_medium_october">אוק</string>
-    <string name="month_medium_november">נוב</string>
-    <string name="month_medium_december">דצמ</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">יום ראשון</string>
-    <string name="day_of_week_long_monday">יום שני</string>
-    <string name="day_of_week_long_tuesday">יום שלישי</string>
-    <string name="day_of_week_long_wednesday">יום רביעי</string>
-    <string name="day_of_week_long_thursday">יום חמישי</string>
-    <string name="day_of_week_long_friday">יום שישי</string>
-    <string name="day_of_week_long_saturday">יום שבת</string>
-
-    <string name="day_of_week_medium_sunday">יום א\'</string>
-    <string name="day_of_week_medium_monday">יום ב\'</string>
-    <string name="day_of_week_medium_tuesday">יום ג\'</string>
-    <string name="day_of_week_medium_wednesday">יום ד\'</string>
-    <string name="day_of_week_medium_thursday">יום ה\'</string>
-    <string name="day_of_week_medium_friday">יום ו\'</string>
-    <string name="day_of_week_medium_saturday">שבת</string>
-
-    <string name="day_of_week_short_sunday">יום א\'</string>
-    <string name="day_of_week_short_monday">יום ב\'</string>
-    <string name="day_of_week_short_tuesday">יום ג\'</string>
-    <string name="day_of_week_short_wednesday">יום ד\'</string>
-    <string name="day_of_week_short_thursday">יום ה\'</string>
-    <string name="day_of_week_short_friday">יום ו\'</string>
-    <string name="day_of_week_short_saturday">שבת</string>
-
-    <string name="day_of_week_shortest_sunday">א</string>
-    <string name="day_of_week_shortest_monday">ב</string>
-    <string name="day_of_week_shortest_tuesday">ג</string>
-    <string name="day_of_week_shortest_wednesday">ד</string>
-    <string name="day_of_week_shortest_thursday">ה</string>
-    <string name="day_of_week_shortest_friday">ו</string>
-    <string name="day_of_week_shortest_saturday">ש</string>
-
-    <string name="am">לפנה"צ</string>
-    <string name="pm">אחה"צ</string>
-    <string name="yesterday">אתמול</string>
-    <string name="today">היום</string>
-    <string name="tomorrow">מחר</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d/%m/%Y</string>
-    <string name="numeric_date_format">dd/MM/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e ב%B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %-e.%-m.%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
-    <string name="month_day">%-e ב%B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y %b</string>
-    <string name="time1_time2">%1$s – %2$s</string>
-    <string name="date1_date2">%2$s – %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s – %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s – %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s – %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s ב%2$s – %8$s ב%7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s ב%2$s – %10$s %8$s ב%7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s ב%2$s – %10$s %8$s ב%7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s – %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-hu-rHU/donottranslate-cldr.xml b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
index 08a70b8..1940889 100644
--- a/core/res/res/values-hu-rHU/donottranslate-cldr.xml
+++ b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
@@ -92,18 +92,18 @@
     <string name="tomorrow">holnap</string>
 
     <string name="hour_minute_24">%H:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
+    <string name="hour_minute_ampm">%p %-l:%M</string>
+    <string name="hour_minute_cap_ampm">%^p %-l:%M</string>
+    <string name="twelve_hour_time_format">a h:mm</string>
     <string name="twenty_four_hour_time_format">HH:mm</string>
     <string name="numeric_date">%Y.%m.%d.</string>
     <string name="numeric_date_format">yyyy.MM.dd.</string>
     <string name="numeric_date_template">"%s.%s.%s."</string>
     <string name="month_day_year">%Y. %B %-e.</string>
     <string name="time_of_day">%-k:%M:%S</string>
-    <string name="date_and_time">%-k:%M:%S %Y.%m.%d.</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
+    <string name="date_and_time">%Y.%m.%d., %-k:%M:%S</string>
+    <string name="date_time">%1$s, %2$s</string>
+    <string name="time_date">%3$s, %1$s</string>
     <string name="abbrev_month_day_year">%Y.%m.%d.</string>
     <string name="month_day">%B %-e.</string>
     <string name="month">%-B</string>
@@ -117,26 +117,26 @@
     <string name="numeric_wday1_md1_wday2_md2">%2$s.%3$s., %1$s - %7$s.%8$s., %6$s</string>
     <string name="numeric_mdy1_mdy2">%4$s.%2$s.%3$s. - %9$s.%7$s.%8$s.</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s.%2$s.%3$s., %1$s - %9$s.%7$s.%8$s., %6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s.%2$s.%3$s., %1$s - %10$s %9$s.%7$s.%8$s., %6$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s. %3$s. - %10$s %7$s. %8$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s. %3$s., %1$s - %10$s %7$s. %8$s., %6$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s.%2$s.%3$s. - %10$s %9$s.%7$s.%8$s.</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s, %1$s - %6$s %5$s, %4$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%4$s.%2$s.%3$s., %1$s, %5$s - %9$s.%7$s.%8$s., %6$s, %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%2$s.%3$s., %5$s - %7$s.%8$s., %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%2$s.%3$s., %1$s, %5$s - %7$s.%8$s., %6$s, %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%4$s.%2$s.%3$s., %5$s - %9$s.%7$s.%8$s., %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%2$s, %1$s, %3$s - %5$s, %4$s, %6$s</string>
     <string name="wday1_date1_wday2_date2">%2$s, %1$s - %5$s, %4$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s, %2$s</string>
+    <string name="date1_time1_date2_time2">%2$s, %3$s - %5$s, %6$s</string>
+    <string name="time_wday_date">%3$s, %2$s, %1$s</string>
     <string name="wday_date">%3$s, %2$s</string>
-    <string name="time_wday">%1$s %2$s</string>
+    <string name="time_wday">%2$s, %1$s</string>
     <string name="same_year_md1_md2">%2$s %3$s. - %7$s %8$s.</string>
     <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s., %1$s - %7$s %8$s., %6$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s. - %10$s %7$s %8$s.</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s. - %10$s %7$s %8$s.</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s., %1$s - %10$s %7$s %8$s., %6$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s., %1$s - %10$s %7$s %8$s., %6$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s. %2$s %3$s. - %10$s %9$s. %7$s %8$s.</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s. %2$s %3$s. - %10$s %9$s. %7$s %8$s.</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s %3$s., %1$s - %10$s %9$s. %7$s %8$s., %6$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s %3$s., %1$s - %10$s %9$s. %7$s %8$s., %6$s</string>
+    <string name="same_year_md1_time1_md2_time2">%2$s %3$s., %5$s - %7$s %8$s., %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%2$s %3$s., %5$s - %7$s %8$s., %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%2$s %3$s., %1$s, %5$s - %7$s %8$s., %6$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%2$s %3$s., %1$s, %5$s - %7$s %8$s., %6$s, %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%4$s. %2$s %3$s., %5$s - %9$s. %7$s %8$s., %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%4$s. %2$s %3$s., %5$s - %9$s. %7$s %8$s., %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%4$s. %2$s %3$s., %1$s, %5$s - %9$s. %7$s %8$s., %6$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%4$s. %2$s %3$s., %1$s, %5$s - %9$s. %7$s %8$s., %6$s, %10$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s. %2$s %3$s., %1$s - %9$s. %7$s %8$s., %6$s</string>
     <string name="same_month_md1_md2">%2$s %3$s-%8$s.</string>
     <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s., %1$s - %7$s %8$s., %6$s</string>
diff --git a/core/res/res/values-id-rID/donottranslate-cldr.xml b/core/res/res/values-id-rID/donottranslate-cldr.xml
index 6adec84b..ee33241 100644
--- a/core/res/res/values-id-rID/donottranslate-cldr.xml
+++ b/core/res/res/values-id-rID/donottranslate-cldr.xml
@@ -99,49 +99,49 @@
     <string name="numeric_date">%d/%m/%Y</string>
     <string name="numeric_date_format">dd/MM/yyyy</string>
     <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e %B %Y</string>
     <string name="time_of_day">%H:%M:%S</string>
     <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
     <string name="date_time">%2$s %1$s</string>
     <string name="time_date">%1$s %3$s</string>
     <string name="abbrev_month_day_year">%-e %b %Y</string>
-    <string name="month_day">%B %-e</string>
+    <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
+    <string name="month_day_year">%-e %B %Y</string>
     <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
+    <string name="abbrev_month_day">%-e %b</string>
     <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y %b</string>
+    <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s – %2$s</string>
     <string name="date1_date2">%2$s – %5$s</string>
-    <string name="numeric_md1_md2">%2$s-%3$s – %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s – %6$s, %7$s-%8$s</string>
-    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s – %9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s – %6$s, %9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s – %10$s %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_md1_md2">%3$s-%2$s – %8$s-%7$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s-%2$s – %6$s, %8$s-%7$s</string>
+    <string name="numeric_mdy1_mdy2">%3$s-%2$s-%4$s – %8$s-%7$s-%9$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s-%2$s-%4$s – %6$s, %8$s-%7$s-%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s-%2$s-%4$s – %10$s %6$s, %8$s-%7$s-%9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s-%2$s – %10$s %8$s-%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s-%2$s – %10$s %6$s, %8$s-%7$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s – %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s – %6$s %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s – %4$s, %5$s</string>
     <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%2$s %3$s – %7$s %8$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s – %10$s %7$s %8$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s – %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_md1_md2">%2$s-%3$s – %8$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
-    <string name="same_year_mdy1_mdy2">%9$s-%2$s-%3$s – %7$s-%8$s</string>
-    <string name="same_month_mdy1_mdy2">%9$s-%2$s-%3$s – %8$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s-%2$s-%3$s – %6$s, yyyy-%7$s-%8$s</string>
+    <string name="same_year_md1_md2">%3$s %2$s – %8$s %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s – %6$s, %8$s %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s – %10$s %6$s, %8$s %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s – %10$s %6$s, %8$s %7$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s – %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_md1_md2">%3$s - %8$s %2$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s – %6$s, %8$s %7$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
+    <string name="same_month_mdy1_mdy2">%3$s - %8$s %2$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-it-rCH/donottranslate-cldr.xml b/core/res/res/values-it-rCH/donottranslate-cldr.xml
deleted file mode 100644
index 12170d6c..0000000
--- a/core/res/res/values-it-rCH/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Gennaio</string>
-    <string name="month_long_standalone_february">Febbraio</string>
-    <string name="month_long_standalone_march">Marzo</string>
-    <string name="month_long_standalone_april">Aprile</string>
-    <string name="month_long_standalone_may">Maggio</string>
-    <string name="month_long_standalone_june">Giugno</string>
-    <string name="month_long_standalone_july">Luglio</string>
-    <string name="month_long_standalone_august">Agosto</string>
-    <string name="month_long_standalone_september">Settembre</string>
-    <string name="month_long_standalone_october">Ottobre</string>
-    <string name="month_long_standalone_november">Novembre</string>
-    <string name="month_long_standalone_december">Dicembre</string>
-
-    <string name="month_long_january">gennaio</string>
-    <string name="month_long_february">febbraio</string>
-    <string name="month_long_march">marzo</string>
-    <string name="month_long_april">aprile</string>
-    <string name="month_long_may">maggio</string>
-    <string name="month_long_june">giugno</string>
-    <string name="month_long_july">luglio</string>
-    <string name="month_long_august">agosto</string>
-    <string name="month_long_september">settembre</string>
-    <string name="month_long_october">ottobre</string>
-    <string name="month_long_november">novembre</string>
-    <string name="month_long_december">dicembre</string>
-
-    <string name="month_medium_january">gen</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">apr</string>
-    <string name="month_medium_may">mag</string>
-    <string name="month_medium_june">giu</string>
-    <string name="month_medium_july">lug</string>
-    <string name="month_medium_august">ago</string>
-    <string name="month_medium_september">set</string>
-    <string name="month_medium_october">ott</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dic</string>
-
-    <string name="month_shortest_january">G</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">G</string>
-    <string name="month_shortest_july">L</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">domenica</string>
-    <string name="day_of_week_long_monday">lunedì</string>
-    <string name="day_of_week_long_tuesday">martedì</string>
-    <string name="day_of_week_long_wednesday">mercoledì</string>
-    <string name="day_of_week_long_thursday">giovedì</string>
-    <string name="day_of_week_long_friday">venerdì</string>
-    <string name="day_of_week_long_saturday">sabato</string>
-
-    <string name="day_of_week_medium_sunday">dom</string>
-    <string name="day_of_week_medium_monday">lun</string>
-    <string name="day_of_week_medium_tuesday">mar</string>
-    <string name="day_of_week_medium_wednesday">mer</string>
-    <string name="day_of_week_medium_thursday">gio</string>
-    <string name="day_of_week_medium_friday">ven</string>
-    <string name="day_of_week_medium_saturday">sab</string>
-
-    <string name="day_of_week_short_sunday">dom</string>
-    <string name="day_of_week_short_monday">lun</string>
-    <string name="day_of_week_short_tuesday">mar</string>
-    <string name="day_of_week_short_wednesday">mer</string>
-    <string name="day_of_week_short_thursday">gio</string>
-    <string name="day_of_week_short_friday">ven</string>
-    <string name="day_of_week_short_saturday">sab</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">G</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">m.</string>
-    <string name="pm">p.</string>
-    <string name="yesterday">ieri</string>
-    <string name="today">oggi</string>
-    <string name="tomorrow">domani</string>
-
-    <string name="hour_minute_24">%H:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">HH:mm</string>
-    <string name="numeric_date">%d.%m.%Y</string>
-    <string name="numeric_date_format">dd.MM.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
-    <string name="month_day_year">%-e %B %Y</string>
-    <string name="time_of_day">%H.%M.%S</string>
-    <string name="date_and_time">%H.%M.%S %-e-%b-%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e-%b-%Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s - %10$s %6$s, %8$s.%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s - %10$s %6$s, %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s - %10$s %6$s, %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-it-rIT/donottranslate-cldr.xml b/core/res/res/values-it-rIT/donottranslate-cldr.xml
deleted file mode 100644
index 2178bbe..0000000
--- a/core/res/res/values-it-rIT/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Gennaio</string>
-    <string name="month_long_standalone_february">Febbraio</string>
-    <string name="month_long_standalone_march">Marzo</string>
-    <string name="month_long_standalone_april">Aprile</string>
-    <string name="month_long_standalone_may">Maggio</string>
-    <string name="month_long_standalone_june">Giugno</string>
-    <string name="month_long_standalone_july">Luglio</string>
-    <string name="month_long_standalone_august">Agosto</string>
-    <string name="month_long_standalone_september">Settembre</string>
-    <string name="month_long_standalone_october">Ottobre</string>
-    <string name="month_long_standalone_november">Novembre</string>
-    <string name="month_long_standalone_december">Dicembre</string>
-
-    <string name="month_long_january">gennaio</string>
-    <string name="month_long_february">febbraio</string>
-    <string name="month_long_march">marzo</string>
-    <string name="month_long_april">aprile</string>
-    <string name="month_long_may">maggio</string>
-    <string name="month_long_june">giugno</string>
-    <string name="month_long_july">luglio</string>
-    <string name="month_long_august">agosto</string>
-    <string name="month_long_september">settembre</string>
-    <string name="month_long_october">ottobre</string>
-    <string name="month_long_november">novembre</string>
-    <string name="month_long_december">dicembre</string>
-
-    <string name="month_medium_january">gen</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">apr</string>
-    <string name="month_medium_may">mag</string>
-    <string name="month_medium_june">giu</string>
-    <string name="month_medium_july">lug</string>
-    <string name="month_medium_august">ago</string>
-    <string name="month_medium_september">set</string>
-    <string name="month_medium_october">ott</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dic</string>
-
-    <string name="month_shortest_january">G</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">G</string>
-    <string name="month_shortest_july">L</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">domenica</string>
-    <string name="day_of_week_long_monday">lunedì</string>
-    <string name="day_of_week_long_tuesday">martedì</string>
-    <string name="day_of_week_long_wednesday">mercoledì</string>
-    <string name="day_of_week_long_thursday">giovedì</string>
-    <string name="day_of_week_long_friday">venerdì</string>
-    <string name="day_of_week_long_saturday">sabato</string>
-
-    <string name="day_of_week_medium_sunday">dom</string>
-    <string name="day_of_week_medium_monday">lun</string>
-    <string name="day_of_week_medium_tuesday">mar</string>
-    <string name="day_of_week_medium_wednesday">mer</string>
-    <string name="day_of_week_medium_thursday">gio</string>
-    <string name="day_of_week_medium_friday">ven</string>
-    <string name="day_of_week_medium_saturday">sab</string>
-
-    <string name="day_of_week_short_sunday">dom</string>
-    <string name="day_of_week_short_monday">lun</string>
-    <string name="day_of_week_short_tuesday">mar</string>
-    <string name="day_of_week_short_wednesday">mer</string>
-    <string name="day_of_week_short_thursday">gio</string>
-    <string name="day_of_week_short_friday">ven</string>
-    <string name="day_of_week_short_saturday">sab</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">G</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">m.</string>
-    <string name="pm">p.</string>
-    <string name="yesterday">ieri</string>
-    <string name="today">oggi</string>
-    <string name="tomorrow">domani</string>
-
-    <string name="hour_minute_24">%H:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">HH:mm</string>
-    <string name="numeric_date">%d/%m/%Y</string>
-    <string name="numeric_date_format">dd/MM/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%d %B %Y</string>
-    <string name="time_of_day">%H.%M.%S</string>
-    <string name="date_and_time">%H.%M.%S %d/%b/%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d/%b/%Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s/%2$s/%4$s - %10$s %6$s, %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-it/donottranslate-cldr.xml b/core/res/res/values-it/donottranslate-cldr.xml
index 2178bbe..5cc697c 100644
--- a/core/res/res/values-it/donottranslate-cldr.xml
+++ b/core/res/res/values-it/donottranslate-cldr.xml
@@ -1,18 +1,18 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Gennaio</string>
-    <string name="month_long_standalone_february">Febbraio</string>
-    <string name="month_long_standalone_march">Marzo</string>
-    <string name="month_long_standalone_april">Aprile</string>
-    <string name="month_long_standalone_may">Maggio</string>
-    <string name="month_long_standalone_june">Giugno</string>
-    <string name="month_long_standalone_july">Luglio</string>
-    <string name="month_long_standalone_august">Agosto</string>
-    <string name="month_long_standalone_september">Settembre</string>
-    <string name="month_long_standalone_october">Ottobre</string>
-    <string name="month_long_standalone_november">Novembre</string>
-    <string name="month_long_standalone_december">Dicembre</string>
+    <string name="month_long_standalone_january">gennaio</string>
+    <string name="month_long_standalone_february">febbraio</string>
+    <string name="month_long_standalone_march">marzo</string>
+    <string name="month_long_standalone_april">aprile</string>
+    <string name="month_long_standalone_may">maggio</string>
+    <string name="month_long_standalone_june">giugno</string>
+    <string name="month_long_standalone_july">luglio</string>
+    <string name="month_long_standalone_august">agosto</string>
+    <string name="month_long_standalone_september">settembre</string>
+    <string name="month_long_standalone_october">ottobre</string>
+    <string name="month_long_standalone_november">novembre</string>
+    <string name="month_long_standalone_december">dicembre</string>
 
     <string name="month_long_january">gennaio</string>
     <string name="month_long_february">febbraio</string>
@@ -100,8 +100,8 @@
     <string name="numeric_date_format">dd/MM/yyyy</string>
     <string name="numeric_date_template">"%s/%s/%s"</string>
     <string name="month_day_year">%d %B %Y</string>
-    <string name="time_of_day">%H.%M.%S</string>
-    <string name="date_and_time">%H.%M.%S %d/%b/%Y</string>
+    <string name="time_of_day">%H:%M:%S</string>
+    <string name="date_and_time">%H:%M:%S %d/%b/%Y</string>
     <string name="date_time">%2$s %1$s</string>
     <string name="time_date">%1$s %3$s</string>
     <string name="abbrev_month_day_year">%d/%b/%Y</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index e05fdb1..778faac 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"Impossibile accedere al file."</string>
     <string name="httpErrorFileNotFound">"Impossibile trovare il file richiesto."</string>
     <string name="httpErrorTooManyRequests">"Troppe richieste in fase di elaborazione. Riprova più tardi."</string>
-    <string name="certificateSaved">"Il certificato viene salvato nell\'archivio chiavi del sistema."</string>
     <string name="contentServiceSync">"Sinc"</string>
     <string name="contentServiceSyncNotificationTitle">"Sincronizzazione"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Troppe eliminazioni di <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-ja-rJP/donottranslate-cldr.xml b/core/res/res/values-ja-rJP/donottranslate-cldr.xml
deleted file mode 100644
index d2510f6..0000000
--- a/core/res/res/values-ja-rJP/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">1月</string>
-    <string name="month_long_standalone_february">2月</string>
-    <string name="month_long_standalone_march">3月</string>
-    <string name="month_long_standalone_april">4月</string>
-    <string name="month_long_standalone_may">5月</string>
-    <string name="month_long_standalone_june">6月</string>
-    <string name="month_long_standalone_july">7月</string>
-    <string name="month_long_standalone_august">8月</string>
-    <string name="month_long_standalone_september">9月</string>
-    <string name="month_long_standalone_october">10月</string>
-    <string name="month_long_standalone_november">11月</string>
-    <string name="month_long_standalone_december">12月</string>
-
-    <string name="month_long_january">1月</string>
-    <string name="month_long_february">2月</string>
-    <string name="month_long_march">3月</string>
-    <string name="month_long_april">4月</string>
-    <string name="month_long_may">5月</string>
-    <string name="month_long_june">6月</string>
-    <string name="month_long_july">7月</string>
-    <string name="month_long_august">8月</string>
-    <string name="month_long_september">9月</string>
-    <string name="month_long_october">10月</string>
-    <string name="month_long_november">11月</string>
-    <string name="month_long_december">12月</string>
-
-    <string name="month_medium_january">1月</string>
-    <string name="month_medium_february">2月</string>
-    <string name="month_medium_march">3月</string>
-    <string name="month_medium_april">4月</string>
-    <string name="month_medium_may">5月</string>
-    <string name="month_medium_june">6月</string>
-    <string name="month_medium_july">7月</string>
-    <string name="month_medium_august">8月</string>
-    <string name="month_medium_september">9月</string>
-    <string name="month_medium_october">10月</string>
-    <string name="month_medium_november">11月</string>
-    <string name="month_medium_december">12月</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">日曜日</string>
-    <string name="day_of_week_long_monday">月曜日</string>
-    <string name="day_of_week_long_tuesday">火曜日</string>
-    <string name="day_of_week_long_wednesday">水曜日</string>
-    <string name="day_of_week_long_thursday">木曜日</string>
-    <string name="day_of_week_long_friday">金曜日</string>
-    <string name="day_of_week_long_saturday">土曜日</string>
-
-    <string name="day_of_week_medium_sunday">日</string>
-    <string name="day_of_week_medium_monday">月</string>
-    <string name="day_of_week_medium_tuesday">火</string>
-    <string name="day_of_week_medium_wednesday">水</string>
-    <string name="day_of_week_medium_thursday">木</string>
-    <string name="day_of_week_medium_friday">金</string>
-    <string name="day_of_week_medium_saturday">土</string>
-
-    <string name="day_of_week_short_sunday">日</string>
-    <string name="day_of_week_short_monday">月</string>
-    <string name="day_of_week_short_tuesday">火</string>
-    <string name="day_of_week_short_wednesday">水</string>
-    <string name="day_of_week_short_thursday">木</string>
-    <string name="day_of_week_short_friday">金</string>
-    <string name="day_of_week_short_saturday">土</string>
-
-    <string name="day_of_week_shortest_sunday">日</string>
-    <string name="day_of_week_shortest_monday">月</string>
-    <string name="day_of_week_shortest_tuesday">火</string>
-    <string name="day_of_week_shortest_wednesday">水</string>
-    <string name="day_of_week_shortest_thursday">木</string>
-    <string name="day_of_week_shortest_friday">金</string>
-    <string name="day_of_week_shortest_saturday">土</string>
-
-    <string name="am">午前</string>
-    <string name="pm">午後</string>
-    <string name="yesterday">昨日</string>
-    <string name="today">今日</string>
-    <string name="tomorrow">明日</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%p%-l:%M</string>
-    <string name="hour_minute_cap_ampm">%p%-l:%M</string>
-    <string name="twelve_hour_time_format">ah:mm</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%Y/%m/%d</string>
-    <string name="numeric_date_format">yyyy/MM/dd</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%Y年%-m月%-e日</string>
-    <string name="time_of_day">%-k:%M:%S</string>
-    <string name="date_and_time">%-k:%M:%S %Y/%m/%d</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%Y/%m/%d</string>
-    <string name="month_day">%-m月%-e日</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%Y年%-m月</string>
-    <string name="abbrev_month_day">%-m月%-e日</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y年%-m月</string>
-    <string name="time1_time2">%1$s~%2$s</string>
-    <string name="date1_date2">%2$s~%5$s</string>
-    <string name="numeric_md1_md2">%2$s/%3$s~%7$s/%8$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%2$s/%3$s(%1$s)~%7$s/%8$s(%6$s)</string>
-    <string name="numeric_mdy1_mdy2">%4$s/%2$s/%3$s~%9$s/%7$s/%8$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s/%2$s/%3$s(%1$s)~%9$s/%7$s/%8$s(%6$s)</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s/%2$s/%3$s(%1$s)~%10$s %9$s/%7$s/%8$s(%6$s)</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s/%3$s~%10$s %7$s/%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s/%3$s(%1$s)~%10$s %7$s/%8$s(%6$s)</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s/%2$s/%3$s~%10$s %9$s/%7$s/%8$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s(%1$s)~%6$s %5$s(%4$s)</string>
-    <string name="wday1_date1_wday2_date2">%2$s(%1$s)~%5$s(%4$s)</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s~%6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s(%2$s)</string>
-    <string name="wday_date">%3$s(%2$s)</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%2$s%3$s日~%7$s%8$s日</string>
-    <string name="same_year_wday1_md1_wday2_md2">%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %2$s%3$s日~%10$s %7$s%8$s日</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %2$s%3$s日~%10$s %7$s%8$s日</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s%3$s日(%1$s)~%10$s %7$s%8$s日(%6$s)</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s%3$s日(%1$s)~%10$s %7$s%8$s日(%6$s)</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s年%2$s%3$s日~%10$s %9$s年%7$s%8$s日</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s年%2$s%3$s日~%10$s %9$s年%7$s%8$s日</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日(%1$s)~%9$s年%7$s%8$s日(%6$s)</string>
-    <string name="same_month_md1_md2">%2$s%3$s日~%8$s日</string>
-    <string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
-    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日~%7$s%8$s日</string>
-    <string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日~%8$s日</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-ja/donottranslate-cldr.xml b/core/res/res/values-ja/donottranslate-cldr.xml
index d2510f6..dab8e2a 100644
--- a/core/res/res/values-ja/donottranslate-cldr.xml
+++ b/core/res/res/values-ja/donottranslate-cldr.xml
@@ -53,13 +53,13 @@
     <string name="month_shortest_november">11</string>
     <string name="month_shortest_december">12</string>
 
-    <string name="day_of_week_long_sunday">日曜日</string>
-    <string name="day_of_week_long_monday">月曜日</string>
-    <string name="day_of_week_long_tuesday">火曜日</string>
-    <string name="day_of_week_long_wednesday">水曜日</string>
-    <string name="day_of_week_long_thursday">木曜日</string>
-    <string name="day_of_week_long_friday">金曜日</string>
-    <string name="day_of_week_long_saturday">土曜日</string>
+    <string name="day_of_week_long_sunday">日</string>
+    <string name="day_of_week_long_monday">月</string>
+    <string name="day_of_week_long_tuesday">火</string>
+    <string name="day_of_week_long_wednesday">水</string>
+    <string name="day_of_week_long_thursday">木</string>
+    <string name="day_of_week_long_friday">金</string>
+    <string name="day_of_week_long_saturday">土</string>
 
     <string name="day_of_week_medium_sunday">日</string>
     <string name="day_of_week_medium_monday">月</string>
@@ -85,25 +85,25 @@
     <string name="day_of_week_shortest_friday">金</string>
     <string name="day_of_week_shortest_saturday">土</string>
 
-    <string name="am">午前</string>
-    <string name="pm">午後</string>
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
     <string name="yesterday">昨日</string>
     <string name="today">今日</string>
     <string name="tomorrow">明日</string>
 
     <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%p%-l:%M</string>
-    <string name="hour_minute_cap_ampm">%p%-l:%M</string>
-    <string name="twelve_hour_time_format">ah:mm</string>
+    <string name="hour_minute_ampm">%-l:%M%p</string>
+    <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
+    <string name="twelve_hour_time_format">h:mma</string>
     <string name="twenty_four_hour_time_format">H:mm</string>
     <string name="numeric_date">%Y/%m/%d</string>
     <string name="numeric_date_format">yyyy/MM/dd</string>
     <string name="numeric_date_template">"%s/%s/%s"</string>
     <string name="month_day_year">%Y年%-m月%-e日</string>
     <string name="time_of_day">%-k:%M:%S</string>
-    <string name="date_and_time">%-k:%M:%S %Y/%m/%d</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
+    <string name="date_and_time">%Y/%m/%d %-k:%M:%S</string>
+    <string name="date_time">%1$s %2$s</string>
+    <string name="time_date">%3$s %1$s</string>
     <string name="abbrev_month_day_year">%Y/%m/%d</string>
     <string name="month_day">%-m月%-e日</string>
     <string name="month">%-B</string>
@@ -114,34 +114,34 @@
     <string name="time1_time2">%1$s~%2$s</string>
     <string name="date1_date2">%2$s~%5$s</string>
     <string name="numeric_md1_md2">%2$s/%3$s~%7$s/%8$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%2$s/%3$s(%1$s)~%7$s/%8$s(%6$s)</string>
+    <string name="numeric_wday1_md1_wday2_md2">%2$s/%3$s (%1$s)~%7$s/%8$s (%6$s)</string>
     <string name="numeric_mdy1_mdy2">%4$s/%2$s/%3$s~%9$s/%7$s/%8$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s/%2$s/%3$s(%1$s)~%9$s/%7$s/%8$s(%6$s)</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s/%2$s/%3$s(%1$s)~%10$s %9$s/%7$s/%8$s(%6$s)</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s/%3$s~%10$s %7$s/%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s/%3$s(%1$s)~%10$s %7$s/%8$s(%6$s)</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s/%2$s/%3$s~%10$s %9$s/%7$s/%8$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s(%1$s)~%6$s %5$s(%4$s)</string>
-    <string name="wday1_date1_wday2_date2">%2$s(%1$s)~%5$s(%4$s)</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s~%6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s(%2$s)</string>
-    <string name="wday_date">%3$s(%2$s)</string>
-    <string name="time_wday">%1$s %2$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s/%2$s/%3$s (%1$s)~%9$s/%7$s/%8$s (%6$s)</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%4$s/%2$s/%3$s (%1$s) %5$s~%9$s/%7$s/%8$s (%6$s) %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%2$s/%3$s %5$s~%7$s/%8$s %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%2$s/%3$s (%1$s) %5$s~%7$s/%8$s (%6$s) %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%4$s/%2$s/%3$s %5$s~%9$s/%7$s/%8$s %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%2$s (%1$s) %3$s~%5$s (%4$s) %6$s</string>
+    <string name="wday1_date1_wday2_date2">%2$s (%1$s)~%5$s (%4$s)</string>
+    <string name="date1_time1_date2_time2">%2$s%3$s~%5$s%6$s</string>
+    <string name="time_wday_date">%3$s (%2$s) %1$s</string>
+    <string name="wday_date">%3$s (%2$s)</string>
+    <string name="time_wday">%2$s %1$s</string>
     <string name="same_year_md1_md2">%2$s%3$s日~%7$s%8$s日</string>
-    <string name="same_year_wday1_md1_wday2_md2">%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %2$s%3$s日~%10$s %7$s%8$s日</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %2$s%3$s日~%10$s %7$s%8$s日</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s%3$s日(%1$s)~%10$s %7$s%8$s日(%6$s)</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s%3$s日(%1$s)~%10$s %7$s%8$s日(%6$s)</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s年%2$s%3$s日~%10$s %9$s年%7$s%8$s日</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s年%2$s%3$s日~%10$s %9$s年%7$s%8$s日</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日(%1$s)~%9$s年%7$s%8$s日(%6$s)</string>
+    <string name="same_year_wday1_md1_wday2_md2">%2$s%3$s日 (%1$s)~%7$s%8$s日 (%6$s)</string>
+    <string name="same_year_md1_time1_md2_time2">%2$s%3$s日%5$s~%7$s%8$s日%10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%2$s%3$s日%5$s~%7$s%8$s日%10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%2$s%3$s日 (%1$s) %5$s~%7$s%8$s日 (%6$s) %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%2$s%3$s日 (%1$s) %5$s~%7$s%8$s日 (%6$s) %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%4$s年%2$s%3$s日%5$s~%9$s年%7$s%8$s日%10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%4$s年%2$s%3$s日%5$s~%9$s年%7$s%8$s日%10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%4$s年%2$s%3$s日 (%1$s) %5$s~%9$s年%7$s%8$s日 (%6$s) %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%4$s年%2$s%3$s日 (%1$s) %5$s~%9$s年%7$s%8$s日 (%6$s) %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日 (%1$s)~%9$s年%7$s%8$s日 (%6$s)</string>
     <string name="same_month_md1_md2">%2$s%3$s日~%8$s日</string>
-    <string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
+    <string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日 (%1$s)~%7$s%8$s日 (%6$s)</string>
     <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日~%7$s%8$s日</string>
     <string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日~%8$s日</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日 (%1$s)~%7$s%8$s日 (%6$s)</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 75ab0e8..4ad87d7 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"ファイルにアクセスできませんでした。"</string>
     <string name="httpErrorFileNotFound">"要求されたファイルが見つかりませんでした。"</string>
     <string name="httpErrorTooManyRequests">"処理中のリクエストが多すぎます。しばらくしてからもう一度試してください。"</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"同期"</string>
     <string name="contentServiceSyncNotificationTitle">"同期"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"<xliff:g id="CONTENT_TYPE">%s</xliff:g>での削除が多すぎます。"</string>
diff --git a/core/res/res/values-ko-rKR/donottranslate-cldr.xml b/core/res/res/values-ko-rKR/donottranslate-cldr.xml
deleted file mode 100644
index 57cd356..0000000
--- a/core/res/res/values-ko-rKR/donottranslate-cldr.xml
+++ /dev/null
@@ -1,135 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">1월</string>
-    <string name="month_long_standalone_february">2월</string>
-    <string name="month_long_standalone_march">3월</string>
-    <string name="month_long_standalone_april">4월</string>
-    <string name="month_long_standalone_may">5월</string>
-    <string name="month_long_standalone_june">6월</string>
-    <string name="month_long_standalone_july">7월</string>
-    <string name="month_long_standalone_august">8월</string>
-    <string name="month_long_standalone_september">9월</string>
-    <string name="month_long_standalone_october">10월</string>
-    <string name="month_long_standalone_november">11월</string>
-    <string name="month_long_standalone_december">12월</string>
-
-    <string name="month_long_january">1월</string>
-    <string name="month_long_february">2월</string>
-    <string name="month_long_march">3월</string>
-    <string name="month_long_april">4월</string>
-    <string name="month_long_may">5월</string>
-    <string name="month_long_june">6월</string>
-    <string name="month_long_july">7월</string>
-    <string name="month_long_august">8월</string>
-    <string name="month_long_september">9월</string>
-    <string name="month_long_october">10월</string>
-    <string name="month_long_november">11월</string>
-    <string name="month_long_december">12월</string>
-
-
-    <string name="month_shortest_january">1월</string>
-    <string name="month_shortest_february">2월</string>
-    <string name="month_shortest_march">3월</string>
-    <string name="month_shortest_april">4월</string>
-    <string name="month_shortest_may">5월</string>
-    <string name="month_shortest_june">6월</string>
-    <string name="month_shortest_july">7월</string>
-    <string name="month_shortest_august">8월</string>
-    <string name="month_shortest_september">9월</string>
-    <string name="month_shortest_october">10월</string>
-    <string name="month_shortest_november">11월</string>
-    <string name="month_shortest_december">12월</string>
-
-    <string name="day_of_week_long_sunday">일요일</string>
-    <string name="day_of_week_long_monday">월요일</string>
-    <string name="day_of_week_long_tuesday">화요일</string>
-    <string name="day_of_week_long_wednesday">수요일</string>
-    <string name="day_of_week_long_thursday">목요일</string>
-    <string name="day_of_week_long_friday">금요일</string>
-    <string name="day_of_week_long_saturday">토요일</string>
-
-    <string name="day_of_week_medium_sunday">일</string>
-    <string name="day_of_week_medium_monday">월</string>
-    <string name="day_of_week_medium_tuesday">화</string>
-    <string name="day_of_week_medium_wednesday">수</string>
-    <string name="day_of_week_medium_thursday">목</string>
-    <string name="day_of_week_medium_friday">금</string>
-    <string name="day_of_week_medium_saturday">토</string>
-
-    <string name="day_of_week_short_sunday">일</string>
-    <string name="day_of_week_short_monday">월</string>
-    <string name="day_of_week_short_tuesday">화</string>
-    <string name="day_of_week_short_wednesday">수</string>
-    <string name="day_of_week_short_thursday">목</string>
-    <string name="day_of_week_short_friday">금</string>
-    <string name="day_of_week_short_saturday">토</string>
-
-    <string name="day_of_week_shortest_sunday">일</string>
-    <string name="day_of_week_shortest_monday">월</string>
-    <string name="day_of_week_shortest_tuesday">화</string>
-    <string name="day_of_week_shortest_wednesday">수</string>
-    <string name="day_of_week_shortest_thursday">목</string>
-    <string name="day_of_week_shortest_friday">금</string>
-    <string name="day_of_week_shortest_saturday">토</string>
-
-    <string name="am">오전</string>
-    <string name="pm">오후</string>
-    <string name="yesterday">어제</string>
-    <string name="today">오늘</string>
-    <string name="tomorrow">내일</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%Y. %-m. %-e.</string>
-    <string name="numeric_date_format">yyyy. M. d.</string>
-    <string name="numeric_date_template">"%s. %s. %s."</string>
-    <string name="month_day_year">%Y년 %-m월 %-e일</string>
-    <string name="time_of_day">%p %-l:%M:%S</string>
-    <string name="date_and_time">%p %-l:%M:%S %Y. %-m. %-e.</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%Y. %-m. %-e.</string>
-    <string name="month_day">%B %-e일</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%Y년 %B</string>
-    <string name="abbrev_month_day">%b %-e일</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y년 %b</string>
-    <string name="time1_time2">%1$s – %2$s</string>
-    <string name="date1_date2">%2$s – %5$s</string>
-    <string name="numeric_md1_md2">%2$s. %3$s ~ %7$s. %8$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%2$s. %3$s %1$s ~ %7$s. %8$s %6$s</string>
-    <string name="numeric_mdy1_mdy2">%4$s. %2$s. %3$s. ~ %9$s. %7$s. %8$s.</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s. %2$s. %3$s. %1$s ~ %9$s. %7$s. %8$s. %6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s. %3$s. %1$s – %10$s %9$s. %7$s. %8$s. %6$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s. %3$s. – %10$s %7$s. %8$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s. %3$s. (%1$s) – %10$s %7$s. %8$s. (%6$s)</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s. %2$s. %3$s. – %10$s %9$s. %7$s. %8$s.</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s (%1$s) – %6$s %5$s (%4$s)</string>
-    <string name="wday1_date1_wday2_date2">%2$s (%1$s) – %5$s (%4$s)</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s (%2$s)</string>
-    <string name="wday_date">%3$s (%2$s)</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%2$s %3$s일 – %7$s %8$s일</string>
-    <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s일 (%1$s) – %7$s %8$s일 (%6$s)</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s일 – %10$s %7$s %8$s일</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s일 – %10$s %7$s %8$s일</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s일 (%1$s) – %10$s %7$s %8$s일 (%6$s)</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s일 (%1$s) – %10$s %7$s %8$s일 (%6$s)</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s년 %2$s %3$s일 – %10$s %9$s년 %7$s %8$s일</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s년 %2$s %3$s일 – %10$s %9$s년 %7$s %8$s일</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s년 %2$s %3$s일 %1$s – %9$s년 %7$s %8$s일 %6$s</string>
-    <string name="same_month_md1_md2">%2$s %3$s일 ~ %8$s일</string>
-    <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s일 (%1$s) – %7$s %8$s일 (%6$s)</string>
-    <string name="same_year_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %7$s %8$s일</string>
-    <string name="same_month_mdy1_mdy2">%9$s년 %2$s %3$s일~%8$s일</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s %8$s일 %6$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-ko/donottranslate-cldr.xml b/core/res/res/values-ko/donottranslate-cldr.xml
index 57cd356..47f8c03 100644
--- a/core/res/res/values-ko/donottranslate-cldr.xml
+++ b/core/res/res/values-ko/donottranslate-cldr.xml
@@ -27,6 +27,18 @@
     <string name="month_long_november">11월</string>
     <string name="month_long_december">12월</string>
 
+    <string name="month_medium_january">1월</string>
+    <string name="month_medium_february">2월</string>
+    <string name="month_medium_march">3월</string>
+    <string name="month_medium_april">4월</string>
+    <string name="month_medium_may">5월</string>
+    <string name="month_medium_june">6월</string>
+    <string name="month_medium_july">7월</string>
+    <string name="month_medium_august">8월</string>
+    <string name="month_medium_september">9월</string>
+    <string name="month_medium_october">10월</string>
+    <string name="month_medium_november">11월</string>
+    <string name="month_medium_december">12월</string>
 
     <string name="month_shortest_january">1월</string>
     <string name="month_shortest_february">2월</string>
@@ -80,56 +92,56 @@
     <string name="tomorrow">내일</string>
 
     <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
+    <string name="hour_minute_ampm">%p %-l:%M</string>
+    <string name="hour_minute_cap_ampm">%p %-l:%M</string>
+    <string name="twelve_hour_time_format">a h:mm</string>
     <string name="twenty_four_hour_time_format">H:mm</string>
     <string name="numeric_date">%Y. %-m. %-e.</string>
     <string name="numeric_date_format">yyyy. M. d.</string>
     <string name="numeric_date_template">"%s. %s. %s."</string>
     <string name="month_day_year">%Y년 %-m월 %-e일</string>
     <string name="time_of_day">%p %-l:%M:%S</string>
-    <string name="date_and_time">%p %-l:%M:%S %Y. %-m. %-e.</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
+    <string name="date_and_time">%Y. %-m. %-e. %p %-l:%M:%S</string>
+    <string name="date_time">%1$s %2$s</string>
+    <string name="time_date">%3$s %1$s</string>
     <string name="abbrev_month_day_year">%Y. %-m. %-e.</string>
     <string name="month_day">%B %-e일</string>
     <string name="month">%-B</string>
     <string name="month_year">%Y년 %B</string>
-    <string name="abbrev_month_day">%b %-e일</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y년 %b</string>
-    <string name="time1_time2">%1$s – %2$s</string>
-    <string name="date1_date2">%2$s – %5$s</string>
+    <string name="abbrev_month_day">%-m. %-e.</string>
+    <string name="abbrev_month">%-m월</string>
+    <string name="abbrev_month_year">%Y. %-m.</string>
+    <string name="time1_time2">%1$s ~ %2$s</string>
+    <string name="date1_date2">%2$s ~ %5$s</string>
     <string name="numeric_md1_md2">%2$s. %3$s ~ %7$s. %8$s</string>
     <string name="numeric_wday1_md1_wday2_md2">%2$s. %3$s %1$s ~ %7$s. %8$s %6$s</string>
     <string name="numeric_mdy1_mdy2">%4$s. %2$s. %3$s. ~ %9$s. %7$s. %8$s.</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s. %2$s. %3$s. %1$s ~ %9$s. %7$s. %8$s. %6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s. %3$s. %1$s – %10$s %9$s. %7$s. %8$s. %6$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s. %3$s. – %10$s %7$s. %8$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s. %3$s. (%1$s) – %10$s %7$s. %8$s. (%6$s)</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s. %2$s. %3$s. – %10$s %9$s. %7$s. %8$s.</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s (%1$s) – %6$s %5$s (%4$s)</string>
-    <string name="wday1_date1_wday2_date2">%2$s (%1$s) – %5$s (%4$s)</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s (%2$s)</string>
-    <string name="wday_date">%3$s (%2$s)</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%2$s %3$s일 – %7$s %8$s일</string>
-    <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s일 (%1$s) – %7$s %8$s일 (%6$s)</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s일 – %10$s %7$s %8$s일</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s일 – %10$s %7$s %8$s일</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s일 (%1$s) – %10$s %7$s %8$s일 (%6$s)</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s일 (%1$s) – %10$s %7$s %8$s일 (%6$s)</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s년 %2$s %3$s일 – %10$s %9$s년 %7$s %8$s일</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s년 %2$s %3$s일 – %10$s %9$s년 %7$s %8$s일</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s년 %2$s %3$s일 %1$s – %9$s년 %7$s %8$s일 %6$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%4$s. %2$s. %3$s. %1$s %5$s ~ %9$s. %7$s. %8$s. %6$s %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%2$s. %3$s. %5$s ~ %7$s. %8$s. %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%2$s. %3$s. %1$s %5$s ~ %7$s. %8$s. %6$s %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%4$s. %2$s. %3$s. %5$s ~ %9$s. %7$s. %8$s. %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%2$s %1$s %3$s ~ %5$s %4$s %6$s</string>
+    <string name="wday1_date1_wday2_date2">%2$s %1$s ~ %5$s %4$s</string>
+    <string name="date1_time1_date2_time2">%2$s %3$s ~ %5$s %6$s</string>
+    <string name="time_wday_date">%3$s %2$s %1$s</string>
+    <string name="wday_date">%3$s %2$s</string>
+    <string name="time_wday">%2$s %1$s</string>
+    <string name="same_year_md1_md2">%2$s %3$s일 ~ %7$s %8$s일</string>
+    <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s일 %1$s ~ %7$s %8$s일 %6$s</string>
+    <string name="same_year_md1_time1_md2_time2">%2$s %3$s일 %5$s ~ %7$s %8$s일 %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%2$s %3$s일 %5$s ~ %7$s %8$s일 %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%2$s %3$s일 %1$s %5$s ~ %7$s %8$s일 %6$s %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%2$s %3$s일 %1$s %5$s ~ %7$s %8$s일 %6$s %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%4$s년 %2$s %3$s일 %5$s ~ %9$s년 %7$s %8$s일 %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%4$s년 %2$s %3$s일 %5$s ~ %9$s년 %7$s %8$s일 %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%4$s년 %2$s %3$s일 %1$s %5$s ~ %9$s년 %7$s %8$s일 %6$s %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%4$s년 %2$s %3$s일 %1$s %5$s ~ %9$s년 %7$s %8$s일 %6$s %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s년 %2$s %3$s일 %1$s ~ %9$s년 %7$s %8$s일 %6$s</string>
     <string name="same_month_md1_md2">%2$s %3$s일 ~ %8$s일</string>
-    <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s일 (%1$s) – %7$s %8$s일 (%6$s)</string>
+    <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s일 %1$s ~ %7$s %8$s일 %6$s</string>
     <string name="same_year_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %7$s %8$s일</string>
-    <string name="same_month_mdy1_mdy2">%9$s년 %2$s %3$s일~%8$s일</string>
+    <string name="same_month_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %8$s일</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s %8$s일 %6$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 099f19c..c3a9c70 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"파일에 액세스할 수 없습니다."</string>
     <string name="httpErrorFileNotFound">"요청한 파일을 찾을 수 없습니다."</string>
     <string name="httpErrorTooManyRequests">"처리 중인 요청이 너무 많습니다. 잠시 후에 다시 시도해 주세요."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"동기화"</string>
     <string name="contentServiceSyncNotificationTitle">"동기화"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"<xliff:g id="CONTENT_TYPE">%s</xliff:g> 삭제가 너무 많습니다."</string>
diff --git a/core/res/res/values-lt-rLT/donottranslate-cldr.xml b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
index 20d58e0..ad410e7 100644
--- a/core/res/res/values-lt-rLT/donottranslate-cldr.xml
+++ b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
@@ -27,18 +27,18 @@
     <string name="month_long_november">lapkričio</string>
     <string name="month_long_december">gruodžio</string>
 
-    <string name="month_medium_january">Sau</string>
-    <string name="month_medium_february">Vas</string>
-    <string name="month_medium_march">Kov</string>
-    <string name="month_medium_april">Bal</string>
-    <string name="month_medium_may">Geg</string>
-    <string name="month_medium_june">Bir</string>
-    <string name="month_medium_july">Lie</string>
-    <string name="month_medium_august">Rgp</string>
-    <string name="month_medium_september">Rgs</string>
-    <string name="month_medium_october">Spl</string>
-    <string name="month_medium_november">Lap</string>
-    <string name="month_medium_december">Grd</string>
+    <string name="month_medium_january">sau.</string>
+    <string name="month_medium_february">vas.</string>
+    <string name="month_medium_march">kov.</string>
+    <string name="month_medium_april">bal.</string>
+    <string name="month_medium_may">geg.</string>
+    <string name="month_medium_june">bir.</string>
+    <string name="month_medium_july">lie.</string>
+    <string name="month_medium_august">rgp.</string>
+    <string name="month_medium_september">rgs.</string>
+    <string name="month_medium_october">spl.</string>
+    <string name="month_medium_november">lap.</string>
+    <string name="month_medium_december">grd.</string>
 
     <string name="month_shortest_january">S</string>
     <string name="month_shortest_february">V</string>
@@ -101,47 +101,47 @@
     <string name="numeric_date_template">"%s-%s-%s"</string>
     <string name="month_day_year">%Y m. %B %-e d.</string>
     <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %Y.%m.%d</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%Y.%m.%d</string>
-    <string name="month_day">%B %-e</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%Y %B</string>
+    <string name="date_and_time">%H:%M:%S, %Y-%m-%d</string>
+    <string name="date_time">%2$s, %1$s</string>
+    <string name="time_date">%1$s, %3$s</string>
+    <string name="abbrev_month_day_year">%Y-%m-%d</string>
+    <string name="month_day">%B %-e d.</string>
+    <string name="month">%B mėn.</string>
+    <string name="month_year">%Y m. %B mėn.</string>
     <string name="abbrev_month_day">%b %-e d.</string>
-    <string name="abbrev_month">%b</string>
-    <string name="abbrev_month_year">%Y m. %b</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%2$s-%3$s - %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%2$s-%3$s%1$s - %7$s-%8$s%6$s</string>
-    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s - %9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s-%2$s-%3$s%1$s - %9$s-%7$s-%8$s%6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s-%2$s-%3$s%1$s - %10$s %9$s-%7$s-%8$s%6$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s - %10$s %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s-%3$s%1$s - %10$s %7$s-%8$s%6$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s - %10$s %9$s-%7$s-%8$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s%1$s - %6$s %5$s%4$s</string>
-    <string name="wday1_date1_wday2_date2">%2$s%1$s - %5$s%4$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s%2$s</string>
-    <string name="wday_date">%3$s%2$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%2$s %3$s - %7$s %8$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s d.%1$s - %7$s %8$s d.%6$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s d.%1$s - %10$s %7$s %8$s d.%6$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s d.%1$s - %10$s %7$s %8$s d.%6$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s m. %2$s %3$s d. - %10$s %9$s m. %7$s %8$s d.</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s m. %2$s %3$s d. - %10$s %9$s m. %7$s %8$s d.</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s m. %2$s %3$s d.,%1$s - %10$s %9$s m. %7$s %8$s d.,%6$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s m. %2$s %3$s d.,%1$s - %10$s %9$s m. %7$s %8$s d.,%6$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s m. %2$s %3$s d.,%1$s - %9$s m. %7$s %8$s d.,%6$s</string>
-    <string name="same_month_md1_md2">%2$s %3$s d.-%8$s d.</string>
-    <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s d.%1$s - %7$s %8$s d.%6$s</string>
-    <string name="same_year_mdy1_mdy2">%9$s m. %2$s %3$s d. - %7$s %8$s d.</string>
-    <string name="same_month_mdy1_mdy2">%9$s m. %2$s %3$s d.-%8$s d.</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s m. %2$s %3$s d.,%1$s - %7$s %8$s d.,%6$s</string>
+    <string name="abbrev_month">%b mėn.</string>
+    <string name="abbrev_month_year">%Y m. %b mėn.</string>
+    <string name="time1_time2">%1$s-%2$s</string>
+    <string name="date1_date2">%2$s-%5$s</string>
+    <string name="numeric_md1_md2">%2$s-%3$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%2$s-%3$s, %1$s-%7$s-%8$s, %6$s</string>
+    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s-%9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s-%2$s-%3$s, %1$s-%9$s-%7$s-%8$s, %6$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %4$s-%2$s-%3$s, %1$s-%10$s, %9$s-%7$s-%8$s, %6$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s, %2$s-%3$s-%10$s, %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s, %2$s-%3$s, %1$s-%10$s, %7$s-%8$s, %6$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s, %4$s-%2$s-%3$s-%10$s, %9$s-%7$s-%8$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s, %2$s, %1$s-%6$s, %5$s, %4$s</string>
+    <string name="wday1_date1_wday2_date2">%2$s, %1$s-%5$s, %4$s</string>
+    <string name="date1_time1_date2_time2">%3$s, %2$s-%6$s, %5$s</string>
+    <string name="time_wday_date">%1$s, %3$s, %2$s</string>
+    <string name="wday_date">%3$s, %2$s</string>
+    <string name="time_wday">%1$s, %2$s</string>
+    <string name="same_year_md1_md2">%2$s %3$s d.-%7$s %8$s d.</string>
+    <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s d., %1$s-%7$s %8$s d., %6$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s, %2$s %3$s d.-%10$s, %7$s %8$s d.</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s, %2$s %3$s d.-%10$s, %7$s %8$s d.</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s, %2$s %3$s d., %1$s-%10$s, %7$s %8$s d., %6$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s, %2$s %3$s d., %1$s-%10$s, %7$s %8$s d., %6$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s, %4$s m. %2$s %3$s d.-%10$s, %9$s m. %7$s %8$s d.</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s, %4$s m. %2$s %3$s d.-%10$s, %9$s m. %7$s %8$s d.</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %4$s m. %2$s %3$s d., %1$s-%10$s, %9$s m. %7$s %8$s d., %6$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %4$s m. %2$s %3$s d., %1$s-%10$s, %9$s m. %7$s %8$s d., %6$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s m. %2$s %3$s d., %1$s-%9$s m. %7$s %8$s d., %6$s</string>
+    <string name="same_month_md1_md2">%2$s %3$s-%8$s d.</string>
+    <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s d., %1$s-%7$s %8$s d., %6$s</string>
+    <string name="same_year_mdy1_mdy2">%9$s m. %2$s %3$s d.-%7$s %8$s d.</string>
+    <string name="same_month_mdy1_mdy2">%9$s m. %2$s %3$s-%8$s d.</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s m. %2$s %3$s d., %1$s-%7$s %8$s d., %6$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-lv-rLV/donottranslate-cldr.xml b/core/res/res/values-lv-rLV/donottranslate-cldr.xml
index 3dec1d2..2c6765a 100644
--- a/core/res/res/values-lv-rLV/donottranslate-cldr.xml
+++ b/core/res/res/values-lv-rLV/donottranslate-cldr.xml
@@ -101,9 +101,9 @@
     <string name="numeric_date_template">"%s.%s.%s"</string>
     <string name="month_day_year">%Y. gada %-e. %B</string>
     <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %Y. gada %-e. %b</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
+    <string name="date_and_time">%Y. gada %-e. %b, %H:%M:%S</string>
+    <string name="date_time">%1$s, %2$s</string>
+    <string name="time_date">%3$s, %1$s</string>
     <string name="abbrev_month_day_year">%Y. gada %-e. %b</string>
     <string name="month_day">%-e. %B</string>
     <string name="month">%-B</string>
@@ -111,37 +111,37 @@
     <string name="abbrev_month_day">%-e. %b</string>
     <string name="abbrev_month">%-b</string>
     <string name="abbrev_month_year">%Y. g. %b</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s–%8$s.%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
+    <string name="time1_time2">%1$s-%2$s</string>
+    <string name="date1_date2">%2$s-%5$s</string>
+    <string name="numeric_md1_md2">%3$s.%2$s.–%8$s.%7$s.</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s.-%6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s.–%8$s.%7$s.%9$s.</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s. – %6$s, %8$s.%7$s.%9$s.</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s. - %10$s %6$s, %8$s.%7$s.%9$s.</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s.–%6$s, %8$s.%7$s.%9$s.</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s.%2$s.%4$s., %5$s-%6$s, %8$s.%7$s.%9$s., %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%3$s.%2$s., %5$s-%8$s.%7$s., %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s.%2$s., %5$s-%6$s, %8$s.%7$s., %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%3$s.%2$s.%4$s, %5$s-%8$s.%7$s.%9$s, %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s-%4$s, %5$s, %6$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s-%4$s, %5$s</string>
+    <string name="date1_time1_date2_time2">%2$s, %3$s-%5$s, %6$s</string>
+    <string name="time_wday_date">%2$s, %3$s, %1$s</string>
     <string name="wday_date">%2$s, %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s. gada %3$s. %2$s - %10$s %9$s. gada %8$s. %7$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s. gada %3$s. %2$s - %10$s %9$s. gada %8$s. %7$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s. g. %3$s. %2$s - %10$s %6$s, %9$s. g. %8$s. %7$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s. g. %3$s. %2$s - %10$s %6$s, %9$s. g. %8$s. %7$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s. g. %3$s. %2$s - %6$s, %9$s. g. %8$s. %7$s</string>
+    <string name="time_wday">%2$s, %1$s</string>
+    <string name="same_year_md1_md2">%3$s. %2$s-%8$s. %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s-%6$s, %8$s. %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%3$s. %2$s, %5$s-%8$s. %7$s, %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%3$s. %2$s, %5$s-%8$s. %7$s, %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s. %2$s, %5$s-%6$s, %8$s. %7$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s. %2$s, %5$s-%6$s, %8$s. %7$s, %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%4$s. gada %3$s. %2$s, %5$s-%9$s. gada %8$s. %7$s, %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%4$s. gada %3$s. %2$s, %5$s-%9$s. gada %8$s. %7$s, %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %4$s. g. %3$s. %2$s, %5$s-%6$s, %9$s. g. %8$s. %7$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %4$s. g. %3$s. %2$s, %5$s-%6$s, %9$s. g. %8$s. %7$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s. g. %3$s. %2$s-%6$s, %9$s. g. %8$s. %7$s</string>
     <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
-    <string name="same_year_mdy1_mdy2">%9$s. gada %3$s. %2$s - %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s-%6$s, %8$s. %7$s</string>
+    <string name="same_year_mdy1_mdy2">%9$s. gada %3$s. %2$s-%8$s. %7$s</string>
     <string name="same_month_mdy1_mdy2">%9$s. gada %3$s.-%8$s. %2$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s. gada %3$s. %2$s - %6$s, y. gada %8$s. %7$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s. gada %3$s. %2$s-%6$s, y. gada %8$s. %7$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-nb-rNO/donottranslate-cldr.xml b/core/res/res/values-nb-rNO/donottranslate-cldr.xml
deleted file mode 100644
index ecf0111..0000000
--- a/core/res/res/values-nb-rNO/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januar</string>
-    <string name="month_long_standalone_february">februar</string>
-    <string name="month_long_standalone_march">mars</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">mai</string>
-    <string name="month_long_standalone_june">juni</string>
-    <string name="month_long_standalone_july">juli</string>
-    <string name="month_long_standalone_august">august</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">desember</string>
-
-    <string name="month_long_january">januar</string>
-    <string name="month_long_february">februar</string>
-    <string name="month_long_march">mars</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">mai</string>
-    <string name="month_long_june">juni</string>
-    <string name="month_long_july">juli</string>
-    <string name="month_long_august">august</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">desember</string>
-
-    <string name="month_medium_january">jan.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mars</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">juni</string>
-    <string name="month_medium_july">juli</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sep.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">des.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">søndag</string>
-    <string name="day_of_week_long_monday">mandag</string>
-    <string name="day_of_week_long_tuesday">tirsdag</string>
-    <string name="day_of_week_long_wednesday">onsdag</string>
-    <string name="day_of_week_long_thursday">torsdag</string>
-    <string name="day_of_week_long_friday">fredag</string>
-    <string name="day_of_week_long_saturday">lørdag</string>
-
-    <string name="day_of_week_medium_sunday">søn.</string>
-    <string name="day_of_week_medium_monday">man.</string>
-    <string name="day_of_week_medium_tuesday">tir.</string>
-    <string name="day_of_week_medium_wednesday">ons.</string>
-    <string name="day_of_week_medium_thursday">tor.</string>
-    <string name="day_of_week_medium_friday">fre.</string>
-    <string name="day_of_week_medium_saturday">lør.</string>
-
-    <string name="day_of_week_short_sunday">søn.</string>
-    <string name="day_of_week_short_monday">man.</string>
-    <string name="day_of_week_short_tuesday">tir.</string>
-    <string name="day_of_week_short_wednesday">ons.</string>
-    <string name="day_of_week_short_thursday">tor.</string>
-    <string name="day_of_week_short_friday">fre.</string>
-    <string name="day_of_week_short_saturday">lør.</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">O</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">L</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">i går</string>
-    <string name="today">i dag</string>
-    <string name="tomorrow">i morgen</string>
-
-    <string name="hour_minute_24">%H.%M</string>
-    <string name="hour_minute_ampm">%-l.%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l.%M %^p</string>
-    <string name="twelve_hour_time_format">h.mm a</string>
-    <string name="twenty_four_hour_time_format">HH.mm</string>
-    <string name="numeric_date">%d.%m.%Y</string>
-    <string name="numeric_date_format">dd.MM.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
-    <string name="month_day_year">%-e. %B %Y</string>
-    <string name="time_of_day">%H.%M.%S</string>
-    <string name="date_and_time">%H.%M.%S %-e. %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e. %b %Y</string>
-    <string name="month_day">%-e. %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e. %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s–%2$s</string>
-    <string name="date1_date2">%2$s–%5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s.–%8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s.%2$s.–%6$s %8$s.%7$s.</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s–%8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s.%2$s.%4$s–%6$s %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s.%2$s.%4$s–%10$s %6$s %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s.–%10$s %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s.%2$s–%10$s %6$s %8$s.%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s–%10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s–%6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s–%4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s–%6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s–%8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s–%6$s %8$s. %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s–%10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s–%10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s–%10$s %6$s %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s–%10$s %6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s–%10$s %8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s–%10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s–%10$s %6$s %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s–%10$s %6$s %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s %4$s–%6$s %8$s. %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s.–%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s–%6$s %8$s. %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s. %2$s–%8$s. %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s.–%8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s–%6$s %8$s. %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 875b4bc..dff943c 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Kunne ikke åpne filen."</string>
     <string name="httpErrorFileNotFound">"Fant ikke den forespurte filen."</string>
     <string name="httpErrorTooManyRequests">"For mange forespørsler blir behandlet. Prøv igjen senere."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Synkronisering"</string>
     <string name="contentServiceSyncNotificationTitle">"Synkronisering"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"For mange slettinger av <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-nl-rBE/donottranslate-cldr.xml b/core/res/res/values-nl-rBE/donottranslate-cldr.xml
deleted file mode 100644
index 680a392..0000000
--- a/core/res/res/values-nl-rBE/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januari</string>
-    <string name="month_long_standalone_february">februari</string>
-    <string name="month_long_standalone_march">maart</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">mei</string>
-    <string name="month_long_standalone_june">juni</string>
-    <string name="month_long_standalone_july">juli</string>
-    <string name="month_long_standalone_august">augustus</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januari</string>
-    <string name="month_long_february">februari</string>
-    <string name="month_long_march">maart</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">mei</string>
-    <string name="month_long_june">juni</string>
-    <string name="month_long_july">juli</string>
-    <string name="month_long_august">augustus</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mrt.</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">mei</string>
-    <string name="month_medium_june">jun.</string>
-    <string name="month_medium_july">jul.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sep.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">zondag</string>
-    <string name="day_of_week_long_monday">maandag</string>
-    <string name="day_of_week_long_tuesday">dinsdag</string>
-    <string name="day_of_week_long_wednesday">woensdag</string>
-    <string name="day_of_week_long_thursday">donderdag</string>
-    <string name="day_of_week_long_friday">vrijdag</string>
-    <string name="day_of_week_long_saturday">zaterdag</string>
-
-    <string name="day_of_week_medium_sunday">zo</string>
-    <string name="day_of_week_medium_monday">ma</string>
-    <string name="day_of_week_medium_tuesday">di</string>
-    <string name="day_of_week_medium_wednesday">wo</string>
-    <string name="day_of_week_medium_thursday">do</string>
-    <string name="day_of_week_medium_friday">vr</string>
-    <string name="day_of_week_medium_saturday">za</string>
-
-    <string name="day_of_week_short_sunday">zo</string>
-    <string name="day_of_week_short_monday">ma</string>
-    <string name="day_of_week_short_tuesday">di</string>
-    <string name="day_of_week_short_wednesday">wo</string>
-    <string name="day_of_week_short_thursday">do</string>
-    <string name="day_of_week_short_friday">vr</string>
-    <string name="day_of_week_short_saturday">za</string>
-
-    <string name="day_of_week_shortest_sunday">Z</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">D</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">D</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">Z</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Gisteren</string>
-    <string name="today">Vandaag</string>
-    <string name="tomorrow">Morgen</string>
-
-    <string name="hour_minute_24">%H:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">HH:mm</string>
-    <string name="numeric_date">%-e/%m/%Y</string>
-    <string name="numeric_date_format">d/MM/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %-e-%b-%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e-%b-%Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e-%b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s - %10$s %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-nl-rNL/donottranslate-cldr.xml b/core/res/res/values-nl-rNL/donottranslate-cldr.xml
deleted file mode 100644
index b6231b6..0000000
--- a/core/res/res/values-nl-rNL/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januari</string>
-    <string name="month_long_standalone_february">februari</string>
-    <string name="month_long_standalone_march">maart</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">mei</string>
-    <string name="month_long_standalone_june">juni</string>
-    <string name="month_long_standalone_july">juli</string>
-    <string name="month_long_standalone_august">augustus</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januari</string>
-    <string name="month_long_february">februari</string>
-    <string name="month_long_march">maart</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">mei</string>
-    <string name="month_long_june">juni</string>
-    <string name="month_long_july">juli</string>
-    <string name="month_long_august">augustus</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mrt.</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">mei</string>
-    <string name="month_medium_june">jun.</string>
-    <string name="month_medium_july">jul.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sep.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">zondag</string>
-    <string name="day_of_week_long_monday">maandag</string>
-    <string name="day_of_week_long_tuesday">dinsdag</string>
-    <string name="day_of_week_long_wednesday">woensdag</string>
-    <string name="day_of_week_long_thursday">donderdag</string>
-    <string name="day_of_week_long_friday">vrijdag</string>
-    <string name="day_of_week_long_saturday">zaterdag</string>
-
-    <string name="day_of_week_medium_sunday">zo</string>
-    <string name="day_of_week_medium_monday">ma</string>
-    <string name="day_of_week_medium_tuesday">di</string>
-    <string name="day_of_week_medium_wednesday">wo</string>
-    <string name="day_of_week_medium_thursday">do</string>
-    <string name="day_of_week_medium_friday">vr</string>
-    <string name="day_of_week_medium_saturday">za</string>
-
-    <string name="day_of_week_short_sunday">zo</string>
-    <string name="day_of_week_short_monday">ma</string>
-    <string name="day_of_week_short_tuesday">di</string>
-    <string name="day_of_week_short_wednesday">wo</string>
-    <string name="day_of_week_short_thursday">do</string>
-    <string name="day_of_week_short_friday">vr</string>
-    <string name="day_of_week_short_saturday">za</string>
-
-    <string name="day_of_week_shortest_sunday">Z</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">D</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">D</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">Z</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Gisteren</string>
-    <string name="today">Vandaag</string>
-    <string name="tomorrow">Morgen</string>
-
-    <string name="hour_minute_24">%H:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">HH:mm</string>
-    <string name="numeric_date">%d-%m-%Y</string>
-    <string name="numeric_date_format">dd-MM-yyyy</string>
-    <string name="numeric_date_template">"%s-%s-%s"</string>
-    <string name="month_day_year">%-e %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e %b %Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e-%b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s-%2$s - %8$s-%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s-%2$s - %6$s %8$s-%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s-%2$s-%4$s - %8$s-%7$s-%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s-%2$s-%4$s - %6$s %8$s-%7$s-%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s-%2$s-%4$s - %10$s %6$s %8$s-%7$s-%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s-%2$s - %10$s %8$s-%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s-%2$s - %10$s %6$s %8$s-%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s-%2$s-%4$s - %10$s %8$s-%7$s-%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-nl/donottranslate-cldr.xml b/core/res/res/values-nl/donottranslate-cldr.xml
index b6231b6..2360e3f 100644
--- a/core/res/res/values-nl/donottranslate-cldr.xml
+++ b/core/res/res/values-nl/donottranslate-cldr.xml
@@ -108,7 +108,7 @@
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e-%b</string>
+    <string name="abbrev_month_day">%-e %b</string>
     <string name="abbrev_month">%-b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5aa1615..2bbd02d 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"Het bestand kan niet worden geopend."</string>
     <string name="httpErrorFileNotFound">"Het opgevraagde bestand is niet gevonden."</string>
     <string name="httpErrorTooManyRequests">"Er worden te veel aanvragen verwerkt. Probeer het later opnieuw."</string>
-    <string name="certificateSaved">"Het certificaat is opgeslagen in de opslagruimte voor sleutels van het systeem."</string>
     <string name="contentServiceSync">"Synchroniseren"</string>
     <string name="contentServiceSyncNotificationTitle">"Synchroniseren"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Te veel verwijderen voor <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-pl-rPL/donottranslate-cldr.xml b/core/res/res/values-pl-rPL/donottranslate-cldr.xml
deleted file mode 100644
index 4ad17bf..0000000
--- a/core/res/res/values-pl-rPL/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">styczeń</string>
-    <string name="month_long_standalone_february">luty</string>
-    <string name="month_long_standalone_march">marzec</string>
-    <string name="month_long_standalone_april">kwiecień</string>
-    <string name="month_long_standalone_may">maj</string>
-    <string name="month_long_standalone_june">czerwiec</string>
-    <string name="month_long_standalone_july">lipiec</string>
-    <string name="month_long_standalone_august">sierpień</string>
-    <string name="month_long_standalone_september">wrzesień</string>
-    <string name="month_long_standalone_october">październik</string>
-    <string name="month_long_standalone_november">listopad</string>
-    <string name="month_long_standalone_december">grudzień</string>
-
-    <string name="month_long_january">stycznia</string>
-    <string name="month_long_february">lutego</string>
-    <string name="month_long_march">marca</string>
-    <string name="month_long_april">kwietnia</string>
-    <string name="month_long_may">maja</string>
-    <string name="month_long_june">czerwca</string>
-    <string name="month_long_july">lipca</string>
-    <string name="month_long_august">sierpnia</string>
-    <string name="month_long_september">września</string>
-    <string name="month_long_october">października</string>
-    <string name="month_long_november">listopada</string>
-    <string name="month_long_december">grudnia</string>
-
-    <string name="month_medium_january">sty</string>
-    <string name="month_medium_february">lut</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">kwi</string>
-    <string name="month_medium_may">maj</string>
-    <string name="month_medium_june">cze</string>
-    <string name="month_medium_july">lip</string>
-    <string name="month_medium_august">sie</string>
-    <string name="month_medium_september">wrz</string>
-    <string name="month_medium_october">paź</string>
-    <string name="month_medium_november">lis</string>
-    <string name="month_medium_december">gru</string>
-
-    <string name="month_shortest_january">s</string>
-    <string name="month_shortest_february">l</string>
-    <string name="month_shortest_march">m</string>
-    <string name="month_shortest_april">k</string>
-    <string name="month_shortest_may">m</string>
-    <string name="month_shortest_june">c</string>
-    <string name="month_shortest_july">l</string>
-    <string name="month_shortest_august">s</string>
-    <string name="month_shortest_september">w</string>
-    <string name="month_shortest_october">p</string>
-    <string name="month_shortest_november">l</string>
-    <string name="month_shortest_december">g</string>
-
-    <string name="day_of_week_long_sunday">niedziela</string>
-    <string name="day_of_week_long_monday">poniedziałek</string>
-    <string name="day_of_week_long_tuesday">wtorek</string>
-    <string name="day_of_week_long_wednesday">środa</string>
-    <string name="day_of_week_long_thursday">czwartek</string>
-    <string name="day_of_week_long_friday">piątek</string>
-    <string name="day_of_week_long_saturday">sobota</string>
-
-    <string name="day_of_week_medium_sunday">niedz.</string>
-    <string name="day_of_week_medium_monday">pon.</string>
-    <string name="day_of_week_medium_tuesday">wt.</string>
-    <string name="day_of_week_medium_wednesday">śr.</string>
-    <string name="day_of_week_medium_thursday">czw.</string>
-    <string name="day_of_week_medium_friday">pt.</string>
-    <string name="day_of_week_medium_saturday">sob.</string>
-
-    <string name="day_of_week_short_sunday">niedz.</string>
-    <string name="day_of_week_short_monday">pon.</string>
-    <string name="day_of_week_short_tuesday">wt.</string>
-    <string name="day_of_week_short_wednesday">śr.</string>
-    <string name="day_of_week_short_thursday">czw.</string>
-    <string name="day_of_week_short_friday">pt.</string>
-    <string name="day_of_week_short_saturday">sob.</string>
-
-    <string name="day_of_week_shortest_sunday">N</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">W</string>
-    <string name="day_of_week_shortest_wednesday">Ś</string>
-    <string name="day_of_week_shortest_thursday">C</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Wczoraj</string>
-    <string name="today">Dzisiaj</string>
-    <string name="tomorrow">Jutro</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d-%m-%Y</string>
-    <string name="numeric_date_format">dd-MM-yyyy</string>
-    <string name="numeric_date_template">"%s-%s-%s"</string>
-    <string name="month_day_year">%-e %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d-%m-%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d-%m-%Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%-B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y %b</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s-%8$s.%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s-%8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s-%2$s-%4$s-%6$s, %8$s-%7$s-%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s-%2$s-%4$s - %10$s %8$s-%7$s-%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%3$s %2$s %1$s - %8$s %7$s %6$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%3$s %2$s %1$s - %8$s %7$s %6$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-pl/donottranslate-cldr.xml b/core/res/res/values-pl/donottranslate-cldr.xml
index 4ad17bf..f20a5b7 100644
--- a/core/res/res/values-pl/donottranslate-cldr.xml
+++ b/core/res/res/values-pl/donottranslate-cldr.xml
@@ -96,52 +96,52 @@
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
     <string name="twelve_hour_time_format">h:mm a</string>
     <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d-%m-%Y</string>
-    <string name="numeric_date_format">dd-MM-yyyy</string>
-    <string name="numeric_date_template">"%s-%s-%s"</string>
+    <string name="numeric_date">%d.%m.%Y</string>
+    <string name="numeric_date_format">dd.MM.yyyy</string>
+    <string name="numeric_date_template">"%s.%s.%s"</string>
     <string name="month_day_year">%-e %B %Y</string>
     <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d-%m-%Y</string>
-    <string name="date_time">%2$s %1$s</string>
+    <string name="date_and_time">%d.%m.%Y %H:%M:%S</string>
+    <string name="date_time">%1$s %2$s</string>
     <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d-%m-%Y</string>
+    <string name="abbrev_month_day_year">%d.%m.%Y</string>
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%-B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
+    <string name="abbrev_month_day">%-e %b</string>
     <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y %b</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
+    <string name="abbrev_month_year">%b %Y</string>
+    <string name="time1_time2">%1$s-%2$s</string>
+    <string name="date1_date2">%2$s-%5$s</string>
     <string name="numeric_md1_md2">%3$s.%2$s-%8$s.%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s-%6$s, %8$s.%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s-%8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s-%2$s-%4$s-%6$s, %8$s-%7$s-%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s-%2$s-%4$s - %10$s %8$s-%7$s-%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s-%6$s, %8$s.%7$s.%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s.%2$s.%4$s %5$s-%6$s, %8$s.%7$s.%9$s %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%3$s.%2$s %5$s-%8$s.%7$s %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s.%2$s %5$s-%6$s, %8$s.%7$s %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%3$s.%2$s.%4$s %5$s-%8$s.%7$s.%9$s %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s %3$s-%4$s, %5$s %6$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s-%4$s, %5$s</string>
+    <string name="date1_time1_date2_time2">%2$s %3$s-%5$s %6$s</string>
     <string name="time_wday_date">%1$s %2$s, %3$s</string>
     <string name="wday_date">%2$s, %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%3$s %2$s %1$s - %8$s %7$s %6$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
+    <string name="same_year_md1_md2">%3$s %2$s-%8$s %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s-%6$s, %8$s %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%3$s %2$s %5$s-%8$s %7$s %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%3$s %2$s %5$s-%8$s %7$s %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s %5$s-%6$s, %8$s %7$s %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s %5$s-%6$s, %8$s %7$s %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s %5$s-%8$s %7$s %9$s %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s %5$s-%8$s %7$s %9$s %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s %5$s-%6$s, %8$s %7$s %9$s %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s %5$s-%6$s, %8$s %7$s %9$s %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s-%6$s, %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%3$s %2$s %1$s - %8$s %7$s %6$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s-%6$s, %8$s %7$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s %2$s-%8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s-%6$s, %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 6c65869..3f7921d 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"Nie można uzyskać dostępu do pliku."</string>
     <string name="httpErrorFileNotFound">"Nie znaleziono żądanego pliku."</string>
     <string name="httpErrorTooManyRequests">"Zbyt wiele żądań jest przetwarzanych. Spróbuj ponownie później."</string>
-    <string name="certificateSaved">"Certyfikat jest zapisywany w magazynie kluczy systemu."</string>
     <string name="contentServiceSync">"Synchronizacja"</string>
     <string name="contentServiceSyncNotificationTitle">"Synchronizuj"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Zbyt wiele usuwanych <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-pt-rBR/donottranslate-cldr.xml b/core/res/res/values-pt-rBR/donottranslate-cldr.xml
deleted file mode 100644
index 1111658..0000000
--- a/core/res/res/values-pt-rBR/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">janeiro</string>
-    <string name="month_long_standalone_february">fevereiro</string>
-    <string name="month_long_standalone_march">março</string>
-    <string name="month_long_standalone_april">abril</string>
-    <string name="month_long_standalone_may">maio</string>
-    <string name="month_long_standalone_june">junho</string>
-    <string name="month_long_standalone_july">julho</string>
-    <string name="month_long_standalone_august">agosto</string>
-    <string name="month_long_standalone_september">setembro</string>
-    <string name="month_long_standalone_october">outubro</string>
-    <string name="month_long_standalone_november">novembro</string>
-    <string name="month_long_standalone_december">dezembro</string>
-
-    <string name="month_long_january">janeiro</string>
-    <string name="month_long_february">fevereiro</string>
-    <string name="month_long_march">março</string>
-    <string name="month_long_april">abril</string>
-    <string name="month_long_may">maio</string>
-    <string name="month_long_june">junho</string>
-    <string name="month_long_july">julho</string>
-    <string name="month_long_august">agosto</string>
-    <string name="month_long_september">setembro</string>
-    <string name="month_long_october">outubro</string>
-    <string name="month_long_november">novembro</string>
-    <string name="month_long_december">dezembro</string>
-
-    <string name="month_medium_january">jan</string>
-    <string name="month_medium_february">fev</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">abr</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">jun</string>
-    <string name="month_medium_july">jul</string>
-    <string name="month_medium_august">ago</string>
-    <string name="month_medium_september">set</string>
-    <string name="month_medium_october">out</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dez</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">domingo</string>
-    <string name="day_of_week_long_monday">segunda-feira</string>
-    <string name="day_of_week_long_tuesday">terça-feira</string>
-    <string name="day_of_week_long_wednesday">quarta-feira</string>
-    <string name="day_of_week_long_thursday">quinta-feira</string>
-    <string name="day_of_week_long_friday">sexta-feira</string>
-    <string name="day_of_week_long_saturday">sábado</string>
-
-    <string name="day_of_week_medium_sunday">dom</string>
-    <string name="day_of_week_medium_monday">seg</string>
-    <string name="day_of_week_medium_tuesday">ter</string>
-    <string name="day_of_week_medium_wednesday">qua</string>
-    <string name="day_of_week_medium_thursday">qui</string>
-    <string name="day_of_week_medium_friday">sex</string>
-    <string name="day_of_week_medium_saturday">sáb</string>
-
-    <string name="day_of_week_short_sunday">dom</string>
-    <string name="day_of_week_short_monday">seg</string>
-    <string name="day_of_week_short_tuesday">ter</string>
-    <string name="day_of_week_short_wednesday">qua</string>
-    <string name="day_of_week_short_thursday">qui</string>
-    <string name="day_of_week_short_friday">sex</string>
-    <string name="day_of_week_short_saturday">sáb</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">S</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">Q</string>
-    <string name="day_of_week_shortest_thursday">Q</string>
-    <string name="day_of_week_shortest_friday">S</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Ontem</string>
-    <string name="today">Hoje</string>
-    <string name="tomorrow">Amanhã</string>
-
-    <string name="hour_minute_24">%-kh%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H\'h\'mm</string>
-    <string name="numeric_date">%d/%m/%Y</string>
-    <string name="numeric_date_format">dd/MM/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e de %B de %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d/%m/%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d/%m/%Y</string>
-    <string name="month_day">%-e de %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B de %Y</string>
-    <string name="abbrev_month_day">%-e de %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b de %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s/%2$s - %6$s, %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s/%2$s/%4$s - %6$s, %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s/%2$s/%4$s - %10$s %6$s, %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s/%2$s - %10$s %6$s, %8$s/%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s de %2$s - %8$s de %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s de %2$s - %6$s, %8$s de %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s de %2$s - %10$s %6$s, %8$s de %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s de %2$s - %10$s %6$s, %8$s de %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s - %10$s %8$s de %7$s de %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s - %10$s %8$s de %7$s de %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s de %2$s de %4$s - %10$s %6$s, %8$s de %7$s de %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s de %2$s de %4$s - %10$s %6$s, %8$s de %7$s de %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s de %2$s de %4$s - %6$s, %8$s de %7$s de %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s de %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s de %2$s - %6$s, %8$s de %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s de %2$s - %8$s de %7$s de %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s de %2$s de %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s de %2$s - %6$s, %8$s de %7$s de %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 313347b..5b75aad 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Não foi possível aceder ao ficheiro."</string>
     <string name="httpErrorFileNotFound">"Não foi possível localizar o ficheiro pedido."</string>
     <string name="httpErrorTooManyRequests">"Existem demasiados pedidos em processamento. Tente novamente mais tarde."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Sincronização"</string>
     <string name="contentServiceSyncNotificationTitle">"Sincronização"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Demasiadas eliminações de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 214a0ea..4f84872 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Não foi possível acessar o arquivo."</string>
     <string name="httpErrorFileNotFound">"O arquivo solicitado não foi encontrado."</string>
     <string name="httpErrorTooManyRequests">"Há muitas solicitações sendo processadas. Tente novamente mais tarde."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Sincronizar"</string>
     <string name="contentServiceSyncNotificationTitle">"Sincronizar"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Muitas exclusões de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-ru-rRU/donottranslate-cldr.xml b/core/res/res/values-ru-rRU/donottranslate-cldr.xml
deleted file mode 100644
index 21c06ff..0000000
--- a/core/res/res/values-ru-rRU/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Январь</string>
-    <string name="month_long_standalone_february">Февраль</string>
-    <string name="month_long_standalone_march">Март</string>
-    <string name="month_long_standalone_april">Апрель</string>
-    <string name="month_long_standalone_may">Май</string>
-    <string name="month_long_standalone_june">Июнь</string>
-    <string name="month_long_standalone_july">Июль</string>
-    <string name="month_long_standalone_august">Август</string>
-    <string name="month_long_standalone_september">Сентябрь</string>
-    <string name="month_long_standalone_october">Октябрь</string>
-    <string name="month_long_standalone_november">Ноябрь</string>
-    <string name="month_long_standalone_december">Декабрь</string>
-
-    <string name="month_long_january">января</string>
-    <string name="month_long_february">февраля</string>
-    <string name="month_long_march">марта</string>
-    <string name="month_long_april">апреля</string>
-    <string name="month_long_may">мая</string>
-    <string name="month_long_june">июня</string>
-    <string name="month_long_july">июля</string>
-    <string name="month_long_august">августа</string>
-    <string name="month_long_september">сентября</string>
-    <string name="month_long_october">октября</string>
-    <string name="month_long_november">ноября</string>
-    <string name="month_long_december">декабря</string>
-
-    <string name="month_medium_january">янв.</string>
-    <string name="month_medium_february">февр.</string>
-    <string name="month_medium_march">марта</string>
-    <string name="month_medium_april">апр.</string>
-    <string name="month_medium_may">мая</string>
-    <string name="month_medium_june">июня</string>
-    <string name="month_medium_july">июля</string>
-    <string name="month_medium_august">авг.</string>
-    <string name="month_medium_september">сент.</string>
-    <string name="month_medium_october">окт.</string>
-    <string name="month_medium_november">нояб.</string>
-    <string name="month_medium_december">дек.</string>
-
-    <string name="month_shortest_january">Я</string>
-    <string name="month_shortest_february">Ф</string>
-    <string name="month_shortest_march">М</string>
-    <string name="month_shortest_april">А</string>
-    <string name="month_shortest_may">М</string>
-    <string name="month_shortest_june">И</string>
-    <string name="month_shortest_july">И</string>
-    <string name="month_shortest_august">А</string>
-    <string name="month_shortest_september">С</string>
-    <string name="month_shortest_october">О</string>
-    <string name="month_shortest_november">Н</string>
-    <string name="month_shortest_december">Д</string>
-
-    <string name="day_of_week_long_sunday">воскресенье</string>
-    <string name="day_of_week_long_monday">понедельник</string>
-    <string name="day_of_week_long_tuesday">вторник</string>
-    <string name="day_of_week_long_wednesday">среда</string>
-    <string name="day_of_week_long_thursday">четверг</string>
-    <string name="day_of_week_long_friday">пятница</string>
-    <string name="day_of_week_long_saturday">суббота</string>
-
-    <string name="day_of_week_medium_sunday">Вс</string>
-    <string name="day_of_week_medium_monday">Пн</string>
-    <string name="day_of_week_medium_tuesday">Вт</string>
-    <string name="day_of_week_medium_wednesday">Ср</string>
-    <string name="day_of_week_medium_thursday">Чт</string>
-    <string name="day_of_week_medium_friday">Пт</string>
-    <string name="day_of_week_medium_saturday">Сб</string>
-
-    <string name="day_of_week_short_sunday">Вс</string>
-    <string name="day_of_week_short_monday">Пн</string>
-    <string name="day_of_week_short_tuesday">Вт</string>
-    <string name="day_of_week_short_wednesday">Ср</string>
-    <string name="day_of_week_short_thursday">Чт</string>
-    <string name="day_of_week_short_friday">Пт</string>
-    <string name="day_of_week_short_saturday">Сб</string>
-
-    <string name="day_of_week_shortest_sunday">В</string>
-    <string name="day_of_week_shortest_monday">П</string>
-    <string name="day_of_week_shortest_tuesday">В</string>
-    <string name="day_of_week_shortest_wednesday">С</string>
-    <string name="day_of_week_shortest_thursday">Ч</string>
-    <string name="day_of_week_shortest_friday">П</string>
-    <string name="day_of_week_shortest_saturday">С</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Вчера</string>
-    <string name="today">Сегодня</string>
-    <string name="tomorrow">Завтра</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d.%m.%Y</string>
-    <string name="numeric_date_format">dd.MM.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
-    <string name="month_day_year">%-e %B %Y г.</string>
-    <string name="time_of_day">%-k:%M:%S</string>
-    <string name="date_and_time">%-k:%M:%S %d.%m.%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d.%m.%Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s – %6$s, %7$s-%8$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%2$s - %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s</string>
-    <string name="wday_date">%3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s  - %10$s %8$s %7$s %9$s </string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s  - %10$s %8$s %7$s %9$s </string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s г.</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s г.</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s - %8$s %7$s %9$s г.</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-ru/donottranslate-cldr.xml b/core/res/res/values-ru/donottranslate-cldr.xml
index 21c06ff..7745944 100644
--- a/core/res/res/values-ru/donottranslate-cldr.xml
+++ b/core/res/res/values-ru/donottranslate-cldr.xml
@@ -1,18 +1,18 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Январь</string>
-    <string name="month_long_standalone_february">Февраль</string>
-    <string name="month_long_standalone_march">Март</string>
-    <string name="month_long_standalone_april">Апрель</string>
-    <string name="month_long_standalone_may">Май</string>
-    <string name="month_long_standalone_june">Июнь</string>
-    <string name="month_long_standalone_july">Июль</string>
-    <string name="month_long_standalone_august">Август</string>
-    <string name="month_long_standalone_september">Сентябрь</string>
-    <string name="month_long_standalone_october">Октябрь</string>
-    <string name="month_long_standalone_november">Ноябрь</string>
-    <string name="month_long_standalone_december">Декабрь</string>
+    <string name="month_long_standalone_january">январь</string>
+    <string name="month_long_standalone_february">февраль</string>
+    <string name="month_long_standalone_march">март</string>
+    <string name="month_long_standalone_april">апрель</string>
+    <string name="month_long_standalone_may">май</string>
+    <string name="month_long_standalone_june">июнь</string>
+    <string name="month_long_standalone_july">июль</string>
+    <string name="month_long_standalone_august">август</string>
+    <string name="month_long_standalone_september">сентябрь</string>
+    <string name="month_long_standalone_october">октябрь</string>
+    <string name="month_long_standalone_november">ноябрь</string>
+    <string name="month_long_standalone_december">декабрь</string>
 
     <string name="month_long_january">января</string>
     <string name="month_long_february">февраля</string>
@@ -61,21 +61,21 @@
     <string name="day_of_week_long_friday">пятница</string>
     <string name="day_of_week_long_saturday">суббота</string>
 
-    <string name="day_of_week_medium_sunday">Вс</string>
-    <string name="day_of_week_medium_monday">Пн</string>
-    <string name="day_of_week_medium_tuesday">Вт</string>
-    <string name="day_of_week_medium_wednesday">Ср</string>
-    <string name="day_of_week_medium_thursday">Чт</string>
-    <string name="day_of_week_medium_friday">Пт</string>
-    <string name="day_of_week_medium_saturday">Сб</string>
+    <string name="day_of_week_medium_sunday">вс</string>
+    <string name="day_of_week_medium_monday">пн</string>
+    <string name="day_of_week_medium_tuesday">вт</string>
+    <string name="day_of_week_medium_wednesday">ср</string>
+    <string name="day_of_week_medium_thursday">чт</string>
+    <string name="day_of_week_medium_friday">пт</string>
+    <string name="day_of_week_medium_saturday">сб</string>
 
-    <string name="day_of_week_short_sunday">Вс</string>
-    <string name="day_of_week_short_monday">Пн</string>
-    <string name="day_of_week_short_tuesday">Вт</string>
-    <string name="day_of_week_short_wednesday">Ср</string>
-    <string name="day_of_week_short_thursday">Чт</string>
-    <string name="day_of_week_short_friday">Пт</string>
-    <string name="day_of_week_short_saturday">Сб</string>
+    <string name="day_of_week_short_sunday">вс</string>
+    <string name="day_of_week_short_monday">пн</string>
+    <string name="day_of_week_short_tuesday">вт</string>
+    <string name="day_of_week_short_wednesday">ср</string>
+    <string name="day_of_week_short_thursday">чт</string>
+    <string name="day_of_week_short_friday">пт</string>
+    <string name="day_of_week_short_saturday">сб</string>
 
     <string name="day_of_week_shortest_sunday">В</string>
     <string name="day_of_week_shortest_monday">П</string>
@@ -101,45 +101,45 @@
     <string name="numeric_date_template">"%s.%s.%s"</string>
     <string name="month_day_year">%-e %B %Y г.</string>
     <string name="time_of_day">%-k:%M:%S</string>
-    <string name="date_and_time">%-k:%M:%S %d.%m.%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
+    <string name="date_and_time">%-k:%M:%S, %d.%m.%Y</string>
+    <string name="date_time">%2$s, %1$s</string>
+    <string name="time_date">%1$s, %3$s</string>
     <string name="abbrev_month_day_year">%d.%m.%Y</string>
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
+    <string name="month_year">%-B %Y</string>
     <string name="abbrev_month_day">%-e %b</string>
     <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
+    <string name="abbrev_month_year">%-b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
     <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s – %6$s, %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s – %6$s, %8$s.%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%2$s - %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s</string>
-    <string name="wday_date">%3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s, %3$s.%2$s.%4$s - %10$s, %6$s, %8$s.%7$s.%9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s, %3$s.%2$s - %10$s, %8$s.%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s, %3$s.%2$s - %10$s, %6$s, %8$s.%7$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s, %3$s.%2$s.%4$s - %10$s, %8$s.%7$s.%9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s, %1$s, %2$s - %6$s, %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s, %2$s - %6$s, %5$s</string>
+    <string name="time_wday_date">%1$s, %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday">%1$s, %2$s</string>
     <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s  - %10$s %8$s %7$s %9$s </string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s  - %10$s %8$s %7$s %9$s </string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s, %3$s %2$s - %10$s, %8$s %7$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s, %3$s %2$s - %10$s, %8$s %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s, %3$s %2$s - %10$s, %6$s, %8$s %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s, %3$s %2$s - %10$s, %6$s, %8$s %7$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s, %3$s %2$s %4$s - %10$s, %8$s %7$s %9$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s, %3$s %2$s %4$s - %10$s, %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s, %3$s %2$s %4$s - %10$s, %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s, %3$s %2$s %4$s - %10$s, %6$s, %8$s %7$s %9$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s г.</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s г.</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s - %8$s %7$s %9$s г.</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 1078809..22120f6 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Не удается получить доступ к файлу."</string>
     <string name="httpErrorFileNotFound">"Не удалось найти указанные файлы."</string>
     <string name="httpErrorTooManyRequests">"Обрабатывается слишком много запросов. Повторите попытку позднее."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Синхр."</string>
     <string name="contentServiceSyncNotificationTitle">"Синхр."</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Слишком много удалений <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-sk-rSK/donottranslate-cldr.xml b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
index 16239df..6478074 100644
--- a/core/res/res/values-sk-rSK/donottranslate-cldr.xml
+++ b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
@@ -96,52 +96,52 @@
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
     <string name="twelve_hour_time_format">h:mm a</string>
     <string name="twenty_four_hour_time_format">HH:mm</string>
-    <string name="numeric_date">%-e.%-m.%Y</string>
-    <string name="numeric_date_format">d.M.yyyy</string>
-    <string name="numeric_date_template">"%s.%s.%s"</string>
+    <string name="numeric_date">%-e. %-m. %Y</string>
+    <string name="numeric_date_format">d. M. yyyy</string>
+    <string name="numeric_date_template">"%s. %s. %s"</string>
     <string name="month_day_year">%-e. %B %Y</string>
     <string name="time_of_day">%-k:%M:%S</string>
-    <string name="date_and_time">%-k:%M:%S %-e.%-m.%Y</string>
+    <string name="date_and_time">%-k:%M:%S %-e. %-m. %Y</string>
     <string name="date_time">%2$s %1$s</string>
     <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
+    <string name="abbrev_month_day_year">%-e. %-m. %Y</string>
     <string name="month_day">%-e. %B</string>
     <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
+    <string name="month_year">%-B %Y</string>
     <string name="abbrev_month_day">%-e. %b</string>
     <string name="abbrev_month">%b</string>
-    <string name="abbrev_month_year">%b %Y</string>
+    <string name="abbrev_month_year">%-b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="numeric_md1_md2">%3$s. %2$s. - %8$s. %7$s.</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s. %2$s. - %6$s %8$s. %7$s.</string>
+    <string name="numeric_mdy1_mdy2">%3$s. %2$s. %4$s - %8$s. %7$s. %9$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s. %4$s - %6$s %8$s. %7$s. %9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s. %4$s - %10$s %6$s %8$s. %7$s. %9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s. %2$s. - %10$s %8$s. %7$s.</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s. - %10$s %6$s %8$s. %7$s.</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s - %10$s %8$s. %7$s. %9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
     <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday_date">%1$s %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
     <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
     <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s - %10$s %6$s %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s. %2$s %4$s - %10$s %6$s %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s %4$s - %6$s %8$s. %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s. - %8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s. - %8$s. %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s - %6$s %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-sl-rSI/donottranslate-cldr.xml b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
index b4ea32f..ae16782 100644
--- a/core/res/res/values-sl-rSI/donottranslate-cldr.xml
+++ b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
@@ -27,18 +27,18 @@
     <string name="month_long_november">november</string>
     <string name="month_long_december">december</string>
 
-    <string name="month_medium_january">jan</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">apr</string>
-    <string name="month_medium_may">maj</string>
-    <string name="month_medium_june">jun</string>
-    <string name="month_medium_july">jul</string>
-    <string name="month_medium_august">avg</string>
-    <string name="month_medium_september">sep</string>
-    <string name="month_medium_october">okt</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dec</string>
+    <string name="month_medium_january">jan.</string>
+    <string name="month_medium_february">feb.</string>
+    <string name="month_medium_march">mar.</string>
+    <string name="month_medium_april">apr.</string>
+    <string name="month_medium_may">maj.</string>
+    <string name="month_medium_june">jun.</string>
+    <string name="month_medium_july">jul.</string>
+    <string name="month_medium_august">avg.</string>
+    <string name="month_medium_september">sep.</string>
+    <string name="month_medium_october">okt.</string>
+    <string name="month_medium_november">nov.</string>
+    <string name="month_medium_december">dec.</string>
 
     <string name="month_shortest_january">j</string>
     <string name="month_shortest_february">f</string>
@@ -61,21 +61,21 @@
     <string name="day_of_week_long_friday">petek</string>
     <string name="day_of_week_long_saturday">sobota</string>
 
-    <string name="day_of_week_medium_sunday">ned</string>
-    <string name="day_of_week_medium_monday">pon</string>
-    <string name="day_of_week_medium_tuesday">tor</string>
-    <string name="day_of_week_medium_wednesday">sre</string>
-    <string name="day_of_week_medium_thursday">čet</string>
-    <string name="day_of_week_medium_friday">pet</string>
-    <string name="day_of_week_medium_saturday">sob</string>
+    <string name="day_of_week_medium_sunday">ned.</string>
+    <string name="day_of_week_medium_monday">pon.</string>
+    <string name="day_of_week_medium_tuesday">tor.</string>
+    <string name="day_of_week_medium_wednesday">sre.</string>
+    <string name="day_of_week_medium_thursday">čet.</string>
+    <string name="day_of_week_medium_friday">pet.</string>
+    <string name="day_of_week_medium_saturday">sob.</string>
 
-    <string name="day_of_week_short_sunday">ned</string>
-    <string name="day_of_week_short_monday">pon</string>
-    <string name="day_of_week_short_tuesday">tor</string>
-    <string name="day_of_week_short_wednesday">sre</string>
-    <string name="day_of_week_short_thursday">čet</string>
-    <string name="day_of_week_short_friday">pet</string>
-    <string name="day_of_week_short_saturday">sob</string>
+    <string name="day_of_week_short_sunday">ned.</string>
+    <string name="day_of_week_short_monday">pon.</string>
+    <string name="day_of_week_short_tuesday">tor.</string>
+    <string name="day_of_week_short_wednesday">sre.</string>
+    <string name="day_of_week_short_thursday">čet.</string>
+    <string name="day_of_week_short_friday">pet.</string>
+    <string name="day_of_week_short_saturday">sob.</string>
 
     <string name="day_of_week_shortest_sunday">n</string>
     <string name="day_of_week_shortest_monday">p</string>
@@ -101,47 +101,47 @@
     <string name="numeric_date_template">"%s. %s. %s"</string>
     <string name="month_day_year">%d. %B %Y</string>
     <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %-e. %b. %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e. %b. %Y</string>
+    <string name="date_and_time">%H:%M:%S, %-e. %b %Y</string>
+    <string name="date_time">%2$s, %1$s</string>
+    <string name="time_date">%1$s, %3$s</string>
+    <string name="abbrev_month_day_year">%-e. %b %Y</string>
     <string name="month_day">%-e. %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e. %b.</string>
+    <string name="abbrev_month_day">%-e. %b</string>
     <string name="abbrev_month">%b</string>
-    <string name="abbrev_month_year">%b. %Y</string>
-    <string name="time1_time2">%1$s – %2$s</string>
-    <string name="date1_date2">%2$s – %5$s</string>
-    <string name="numeric_md1_md2">%3$s. %2$s. – %8$s. %7$s.</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s.</string>
-    <string name="numeric_mdy1_mdy2">%3$s. %2$s. %4$s – %8$s. %7$s. %9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. %4$s – %6$s., %8$s. %7$s. %9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s. %2$s. – %10$s %8$s. %7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s., %3$s. %2$s. – %10$s %6$s., %8$s. %7$s.</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s., %2$s – %6$s %4$s., %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s., %2$s – %4$s., %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s., %3$s</string>
-    <string name="wday_date">%2$s., %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s. %2$s – %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s.</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s – %10$s %8$s. %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s – %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s., %3$s. %2$s. – %10$s %6$s., %8$s. %7$s.</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s., %3$s. %2$s. – %10$s %6$s., %8$s. %7$s.</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. %4$s – %6$s., %8$s. %7$s. %9$s</string>
-    <string name="same_month_md1_md2">%3$s.–%8$s. %2$s.</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s.</string>
-    <string name="same_year_mdy1_mdy2">%3$s. %2$s. – %8$s. %7$s. %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s.–%8$s. %2$s. %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s. %9$s</string>
+    <string name="abbrev_month_year">%b %Y</string>
+    <string name="time1_time2">%1$s–%2$s</string>
+    <string name="date1_date2">%2$s–%5$s</string>
+    <string name="numeric_md1_md2">%3$s. %2$s.–%8$s. %7$s.</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s. %2$s.–%6$s, %8$s. %7$s.</string>
+    <string name="numeric_mdy1_mdy2">%3$s. %2$s. %4$s–%8$s. %7$s. %9$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s. %4$s–%6$s, %8$s. %7$s. %9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s, %3$s. %2$s. %4$s–%10$s, %6$s, %8$s. %7$s. %9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s, %3$s. %2$s.–%10$s, %8$s. %7$s.</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s, %3$s. %2$s.–%10$s, %6$s, %8$s. %7$s.</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s, %3$s. %2$s. %4$s–%10$s, %8$s. %7$s. %9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s, %1$s, %2$s–%6$s, %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s–%4$s, %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s, %2$s–%6$s, %5$s</string>
+    <string name="time_wday_date">%1$s, %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday">%1$s, %2$s</string>
+    <string name="same_year_md1_md2">%3$s. %2$s–%8$s. %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s–%6$s, %8$s. %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s, %3$s. %2$s–%10$s, %8$s. %7$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s, %3$s. %2$s–%10$s, %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s, %3$s. %2$s–%10$s, %6$s, %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s, %1$s, %3$s. %2$s–%10$s, %6$s, %8$s. %7$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s, %3$s. %2$s %4$s–%10$s, %8$s. %7$s %9$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s, %3$s. %2$s %4$s–%10$s, %8$s. %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s, %3$s. %2$s %4$s–%10$s, %6$s, %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s, %1$s, %3$s. %2$s %4$s–%10$s, %6$s, %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s–%6$s, %8$s. %7$s %9$s</string>
+    <string name="same_month_md1_md2">%3$s.–%8$s. %2$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s–%6$s, %8$s. %7$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s. %2$s–%8$s. %7$s %9$s</string>
+    <string name="same_month_mdy1_mdy2">%3$s.–%8$s. %2$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s–%6$s, %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-sv-rSE/donottranslate-cldr.xml b/core/res/res/values-sv-rSE/donottranslate-cldr.xml
deleted file mode 100644
index a6ffc9a..0000000
--- a/core/res/res/values-sv-rSE/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januari</string>
-    <string name="month_long_standalone_february">februari</string>
-    <string name="month_long_standalone_march">mars</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">maj</string>
-    <string name="month_long_standalone_june">juni</string>
-    <string name="month_long_standalone_july">juli</string>
-    <string name="month_long_standalone_august">augusti</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januari</string>
-    <string name="month_long_february">februari</string>
-    <string name="month_long_march">mars</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">maj</string>
-    <string name="month_long_june">juni</string>
-    <string name="month_long_july">juli</string>
-    <string name="month_long_august">augusti</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">apr</string>
-    <string name="month_medium_may">maj</string>
-    <string name="month_medium_june">jun</string>
-    <string name="month_medium_july">jul</string>
-    <string name="month_medium_august">aug</string>
-    <string name="month_medium_september">sep</string>
-    <string name="month_medium_october">okt</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">söndag</string>
-    <string name="day_of_week_long_monday">måndag</string>
-    <string name="day_of_week_long_tuesday">tisdag</string>
-    <string name="day_of_week_long_wednesday">onsdag</string>
-    <string name="day_of_week_long_thursday">torsdag</string>
-    <string name="day_of_week_long_friday">fredag</string>
-    <string name="day_of_week_long_saturday">lördag</string>
-
-    <string name="day_of_week_medium_sunday">sön</string>
-    <string name="day_of_week_medium_monday">mån</string>
-    <string name="day_of_week_medium_tuesday">tis</string>
-    <string name="day_of_week_medium_wednesday">ons</string>
-    <string name="day_of_week_medium_thursday">tors</string>
-    <string name="day_of_week_medium_friday">fre</string>
-    <string name="day_of_week_medium_saturday">lör</string>
-
-    <string name="day_of_week_short_sunday">sön</string>
-    <string name="day_of_week_short_monday">mån</string>
-    <string name="day_of_week_short_tuesday">tis</string>
-    <string name="day_of_week_short_wednesday">ons</string>
-    <string name="day_of_week_short_thursday">tors</string>
-    <string name="day_of_week_short_friday">fre</string>
-    <string name="day_of_week_short_saturday">lör</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">O</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">L</string>
-
-    <string name="am">f.m.</string>
-    <string name="pm">e.m.</string>
-    <string name="yesterday">igår</string>
-    <string name="today">idag</string>
-    <string name="tomorrow">imorgon</string>
-
-    <string name="hour_minute_24">%-k.%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H.mm</string>
-    <string name="numeric_date">%Y-%m-%d</string>
-    <string name="numeric_date_format">yyyy-MM-dd</string>
-    <string name="numeric_date_template">"%s-%s-%s"</string>
-    <string name="month_day_year">%-e %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e %b %Y</string>
-    <string name="month_day">%-e %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%Y %B</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y %b</string>
-    <string name="time1_time2">%1$s – %2$s</string>
-    <string name="date1_date2">%2$s – %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s – %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s – %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s – %9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s – %6$s, %9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s – %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s – %10$s %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s – %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s – %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s – %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s – %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s – %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s–%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s–%8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s–%6$s %8$s %7$s %9$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-sv/donottranslate-cldr.xml b/core/res/res/values-sv/donottranslate-cldr.xml
index a6ffc9a..0172755 100644
--- a/core/res/res/values-sv/donottranslate-cldr.xml
+++ b/core/res/res/values-sv/donottranslate-cldr.xml
@@ -91,13 +91,13 @@
     <string name="today">idag</string>
     <string name="tomorrow">imorgon</string>
 
-    <string name="hour_minute_24">%-k.%M</string>
+    <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
     <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H.mm</string>
-    <string name="numeric_date">%Y-%m-%d</string>
-    <string name="numeric_date_format">yyyy-MM-dd</string>
+    <string name="twenty_four_hour_time_format">H:mm</string>
+    <string name="numeric_date">%d-%m-%Y</string>
+    <string name="numeric_date_format">dd-MM-yyyy</string>
     <string name="numeric_date_template">"%s-%s-%s"</string>
     <string name="month_day_year">%-e %B %Y</string>
     <string name="time_of_day">%H:%M:%S</string>
@@ -110,17 +110,17 @@
     <string name="month_year">%Y %B</string>
     <string name="abbrev_month_day">%-e %b</string>
     <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y %b</string>
-    <string name="time1_time2">%1$s – %2$s</string>
+    <string name="abbrev_month_year">%b %Y</string>
+    <string name="time1_time2">%1$s–%2$s</string>
     <string name="date1_date2">%2$s – %5$s</string>
     <string name="numeric_md1_md2">%3$s/%2$s – %8$s/%7$s</string>
     <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s – %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s – %9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s – %6$s, %9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_mdy1_mdy2">%3$s-%2$s-%4$s – %8$s-%7$s-%9$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s-%2$s-%4$s – %6$s %8$s-%7$s-%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s-%2$s-%4$s – %10$s %6$s %8$s-%7$s-%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s – %10$s %8$s/%7$s</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s – %10$s %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s – %10$s %9$s-%7$s-%8$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s-%2$s-%4$s – %10$s %8$s-%7$s-%9$s</string>
     <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
     <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
     <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
@@ -140,8 +140,8 @@
     <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s – %6$s %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s–%8$s %2$s</string>
     <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s – %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s–%8$s %7$s %9$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s %2$s – %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s–%6$s %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s – %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 567932f..40d2500 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Det gick inte att komma åt filen."</string>
     <string name="httpErrorFileNotFound">"Den begärda filen hittades inte."</string>
     <string name="httpErrorTooManyRequests">"För många begäranden bearbetas. Försök igen senare."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Synkronisera"</string>
     <string name="contentServiceSyncNotificationTitle">"Synkronisera"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"För många <xliff:g id="CONTENT_TYPE">%s</xliff:g>-borttagningar."</string>
diff --git a/core/res/res/values-tr-rTR/donottranslate-cldr.xml b/core/res/res/values-tr-rTR/donottranslate-cldr.xml
deleted file mode 100644
index d612305..0000000
--- a/core/res/res/values-tr-rTR/donottranslate-cldr.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Ocak</string>
-    <string name="month_long_standalone_february">Şubat</string>
-    <string name="month_long_standalone_march">Mart</string>
-    <string name="month_long_standalone_april">Nisan</string>
-    <string name="month_long_standalone_may">Mayıs</string>
-    <string name="month_long_standalone_june">Haziran</string>
-    <string name="month_long_standalone_july">Temmuz</string>
-    <string name="month_long_standalone_august">Ağustos</string>
-    <string name="month_long_standalone_september">Eylül</string>
-    <string name="month_long_standalone_october">Ekim</string>
-    <string name="month_long_standalone_november">Kasım</string>
-    <string name="month_long_standalone_december">Aralık</string>
-
-    <string name="month_long_january">Ocak</string>
-    <string name="month_long_february">Şubat</string>
-    <string name="month_long_march">Mart</string>
-    <string name="month_long_april">Nisan</string>
-    <string name="month_long_may">Mayıs</string>
-    <string name="month_long_june">Haziran</string>
-    <string name="month_long_july">Temmuz</string>
-    <string name="month_long_august">Ağustos</string>
-    <string name="month_long_september">Eylül</string>
-    <string name="month_long_october">Ekim</string>
-    <string name="month_long_november">Kasım</string>
-    <string name="month_long_december">Aralık</string>
-
-    <string name="month_medium_january">Oca</string>
-    <string name="month_medium_february">Şub</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Nis</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Haz</string>
-    <string name="month_medium_july">Tem</string>
-    <string name="month_medium_august">Ağu</string>
-    <string name="month_medium_september">Eyl</string>
-    <string name="month_medium_october">Eki</string>
-    <string name="month_medium_november">Kas</string>
-    <string name="month_medium_december">Ara</string>
-
-    <string name="month_shortest_january">O</string>
-    <string name="month_shortest_february">Ş</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">N</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">H</string>
-    <string name="month_shortest_july">T</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">E</string>
-    <string name="month_shortest_october">E</string>
-    <string name="month_shortest_november">K</string>
-    <string name="month_shortest_december">A</string>
-
-    <string name="day_of_week_long_sunday">Pazar</string>
-    <string name="day_of_week_long_monday">Pazartesi</string>
-    <string name="day_of_week_long_tuesday">Salı</string>
-    <string name="day_of_week_long_wednesday">Çarşamba</string>
-    <string name="day_of_week_long_thursday">Perşembe</string>
-    <string name="day_of_week_long_friday">Cuma</string>
-    <string name="day_of_week_long_saturday">Cumartesi</string>
-
-    <string name="day_of_week_medium_sunday">Paz</string>
-    <string name="day_of_week_medium_monday">Pzt</string>
-    <string name="day_of_week_medium_tuesday">Sal</string>
-    <string name="day_of_week_medium_wednesday">Çar</string>
-    <string name="day_of_week_medium_thursday">Per</string>
-    <string name="day_of_week_medium_friday">Cum</string>
-    <string name="day_of_week_medium_saturday">Cmt</string>
-
-    <string name="day_of_week_short_sunday">Paz</string>
-    <string name="day_of_week_short_monday">Pzt</string>
-    <string name="day_of_week_short_tuesday">Sal</string>
-    <string name="day_of_week_short_wednesday">Çar</string>
-    <string name="day_of_week_short_thursday">Per</string>
-    <string name="day_of_week_short_friday">Cum</string>
-    <string name="day_of_week_short_saturday">Cmt</string>
-
-    <string name="day_of_week_shortest_sunday">P</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">S</string>
-    <string name="day_of_week_shortest_wednesday">Ç</string>
-    <string name="day_of_week_shortest_thursday">P</string>
-    <string name="day_of_week_shortest_friday">C</string>
-    <string name="day_of_week_shortest_saturday">C</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Dün</string>
-    <string name="today">Bugün</string>
-    <string name="tomorrow">Yarın</string>
-
-    <string name="hour_minute_24">%H:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">HH:mm</string>
-    <string name="numeric_date">%d %m %Y</string>
-    <string name="numeric_date_format">dd MM yyyy</string>
-    <string name="numeric_date_template">"%s %s %s"</string>
-    <string name="month_day_year">%d %B %Y</string>
-    <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d %b %Y</string>
-    <string name="month_day">%d %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%d %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%3$s.%2$s %1$s - %8$s.%7$s %6$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%3$s.%2$s.%4$s %1$s - %8$s.%7$s.%9$s %6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s.%2$s.%4$s %1$s - %10$s %8$s.%7$s.%9$s %6$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %3$s/%2$s %1$s - %10$s %8$s/%7$s %6$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s %1$s - %6$s %5$s %4$s</string>
-    <string name="wday1_date1_wday2_date2">%2$s %1$s - %5$s %4$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s %2$s</string>
-    <string name="wday_date">%3$s %2$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%3$s %2$s %1$s - %8$s %7$s %6$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s %1$s - %10$s %8$s %7$s %9$s %6$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s %1$s - %10$s %8$s %7$s %9$s %6$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%3$s %2$s %4$s %1$s - %8$s %7$s %9$s %6$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%3$s %2$s %1$s - %8$s %7$s %6$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %9$s %1$s - %8$s %7$s y %6$s</string>
-    <string name="short_format_month">%b</string>
-</resources>
diff --git a/core/res/res/values-tr/donottranslate-cldr.xml b/core/res/res/values-tr/donottranslate-cldr.xml
index d612305..fd8e762 100644
--- a/core/res/res/values-tr/donottranslate-cldr.xml
+++ b/core/res/res/values-tr/donottranslate-cldr.xml
@@ -101,9 +101,9 @@
     <string name="numeric_date_template">"%s %s %s"</string>
     <string name="month_day_year">%d %B %Y</string>
     <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %d %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
+    <string name="date_and_time">%d %b %Y %H:%M:%S</string>
+    <string name="date_time">%1$s %2$s</string>
+    <string name="time_date">%3$s %1$s</string>
     <string name="abbrev_month_day_year">%d %b %Y</string>
     <string name="month_day">%d %B</string>
     <string name="month">%-B</string>
@@ -117,31 +117,31 @@
     <string name="numeric_wday1_md1_wday2_md2">%3$s.%2$s %1$s - %8$s.%7$s %6$s</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%3$s.%2$s.%4$s %1$s - %8$s.%7$s.%9$s %6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s.%2$s.%4$s %1$s - %10$s %8$s.%7$s.%9$s %6$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %3$s/%2$s %1$s - %10$s %8$s/%7$s %6$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s %1$s - %6$s %5$s %4$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%3$s.%2$s.%4$s %1$s %5$s - %8$s.%7$s.%9$s %6$s %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%3$s/%2$s %5$s - %8$s/%7$s %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%3$s/%2$s %1$s %5$s - %8$s/%7$s %6$s %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%3$s %2$s %4$s %5$s - %8$s %7$s %9$s %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%2$s %1$s %3$s - %5$s %4$s %6$s</string>
     <string name="wday1_date1_wday2_date2">%2$s %1$s - %5$s %4$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s %2$s</string>
+    <string name="date1_time1_date2_time2">%2$s %3$s - %5$s %6$s</string>
+    <string name="time_wday_date">%3$s %2$s %1$s</string>
     <string name="wday_date">%3$s %2$s</string>
-    <string name="time_wday">%1$s %2$s</string>
+    <string name="time_wday">%2$s %1$s</string>
     <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
     <string name="same_year_wday1_md1_wday2_md2">%3$s %2$s %1$s - %8$s %7$s %6$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s %1$s - %10$s %8$s %7$s %9$s %6$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s %1$s - %10$s %8$s %7$s %9$s %6$s</string>
+    <string name="same_year_md1_time1_md2_time2">%3$s %2$s %5$s - %8$s %7$s %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%3$s %2$s %5$s - %8$s %7$s %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%3$s %2$s %1$s %5$s - %8$s %7$s %6$s %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%3$s %2$s %1$s %5$s - %8$s %7$s %6$s %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s %5$s - %8$s %7$s %9$s %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s %5$s - %8$s %7$s %9$s %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%3$s %2$s %4$s %1$s %5$s - %8$s %7$s %9$s %6$s %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%3$s %2$s %4$s %1$s %5$s - %8$s %7$s %9$s %6$s %10$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%3$s %2$s %4$s %1$s - %8$s %7$s %9$s %6$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
     <string name="same_month_wday1_md1_wday2_md2">%3$s %2$s %1$s - %8$s %7$s %6$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %9$s %1$s - %8$s %7$s y %6$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %1$s - %8$s %7$s %6$s %9$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index ecf7e41..bda67c7 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Dosyaya erişilemedi."</string>
     <string name="httpErrorFileNotFound">"İstenen dosya bulunamadı."</string>
     <string name="httpErrorTooManyRequests">"Çok fazla sayıda istek işleniyor. Daha sonra yeniden deneyin."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Senk."</string>
     <string name="contentServiceSyncNotificationTitle">"Senk."</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Çok fazla <xliff:g id="CONTENT_TYPE">%s</xliff:g> silme var."</string>
diff --git a/core/res/res/values-uk-rUA/donottranslate-cldr.xml b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
index c51f8d1..ed310c8 100644
--- a/core/res/res/values-uk-rUA/donottranslate-cldr.xml
+++ b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
@@ -1,18 +1,18 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Січень</string>
-    <string name="month_long_standalone_february">Лютий</string>
-    <string name="month_long_standalone_march">Березень</string>
-    <string name="month_long_standalone_april">Квітень</string>
-    <string name="month_long_standalone_may">Травень</string>
-    <string name="month_long_standalone_june">Червень</string>
-    <string name="month_long_standalone_july">Липень</string>
-    <string name="month_long_standalone_august">Серпень</string>
-    <string name="month_long_standalone_september">Вересень</string>
-    <string name="month_long_standalone_october">Жовтень</string>
-    <string name="month_long_standalone_november">Листопад</string>
-    <string name="month_long_standalone_december">Грудень</string>
+    <string name="month_long_standalone_january">січень</string>
+    <string name="month_long_standalone_february">лютий</string>
+    <string name="month_long_standalone_march">березень</string>
+    <string name="month_long_standalone_april">квітень</string>
+    <string name="month_long_standalone_may">травень</string>
+    <string name="month_long_standalone_june">червень</string>
+    <string name="month_long_standalone_july">липень</string>
+    <string name="month_long_standalone_august">серпень</string>
+    <string name="month_long_standalone_september">вересень</string>
+    <string name="month_long_standalone_october">жовтень</string>
+    <string name="month_long_standalone_november">листопад</string>
+    <string name="month_long_standalone_december">грудень</string>
 
     <string name="month_long_january">січня</string>
     <string name="month_long_february">лютого</string>
@@ -53,29 +53,29 @@
     <string name="month_shortest_november">Л</string>
     <string name="month_shortest_december">Г</string>
 
-    <string name="day_of_week_long_sunday">Неділя</string>
-    <string name="day_of_week_long_monday">Понеділок</string>
-    <string name="day_of_week_long_tuesday">Вівторок</string>
-    <string name="day_of_week_long_wednesday">Середа</string>
-    <string name="day_of_week_long_thursday">Четвер</string>
-    <string name="day_of_week_long_friday">Пʼятниця</string>
-    <string name="day_of_week_long_saturday">Субота</string>
+    <string name="day_of_week_long_sunday">неділя</string>
+    <string name="day_of_week_long_monday">понеділок</string>
+    <string name="day_of_week_long_tuesday">вівторок</string>
+    <string name="day_of_week_long_wednesday">середа</string>
+    <string name="day_of_week_long_thursday">четвер</string>
+    <string name="day_of_week_long_friday">пʼятниця</string>
+    <string name="day_of_week_long_saturday">субота</string>
 
-    <string name="day_of_week_medium_sunday">Нд</string>
-    <string name="day_of_week_medium_monday">Пн</string>
-    <string name="day_of_week_medium_tuesday">Вт</string>
-    <string name="day_of_week_medium_wednesday">Ср</string>
-    <string name="day_of_week_medium_thursday">Чт</string>
-    <string name="day_of_week_medium_friday">Пт</string>
-    <string name="day_of_week_medium_saturday">Сб</string>
+    <string name="day_of_week_medium_sunday">нд.</string>
+    <string name="day_of_week_medium_monday">пн.</string>
+    <string name="day_of_week_medium_tuesday">вт.</string>
+    <string name="day_of_week_medium_wednesday">ср.</string>
+    <string name="day_of_week_medium_thursday">чт.</string>
+    <string name="day_of_week_medium_friday">пт.</string>
+    <string name="day_of_week_medium_saturday">сб.</string>
 
-    <string name="day_of_week_short_sunday">Нд</string>
-    <string name="day_of_week_short_monday">Пн</string>
-    <string name="day_of_week_short_tuesday">Вт</string>
-    <string name="day_of_week_short_wednesday">Ср</string>
-    <string name="day_of_week_short_thursday">Чт</string>
-    <string name="day_of_week_short_friday">Пт</string>
-    <string name="day_of_week_short_saturday">Сб</string>
+    <string name="day_of_week_short_sunday">нд.</string>
+    <string name="day_of_week_short_monday">пн.</string>
+    <string name="day_of_week_short_tuesday">вт.</string>
+    <string name="day_of_week_short_wednesday">ср.</string>
+    <string name="day_of_week_short_thursday">чт.</string>
+    <string name="day_of_week_short_friday">пт.</string>
+    <string name="day_of_week_short_saturday">сб.</string>
 
     <string name="day_of_week_shortest_sunday">Н</string>
     <string name="day_of_week_shortest_monday">П</string>
@@ -101,47 +101,47 @@
     <string name="numeric_date_template">"%s.%s.%s"</string>
     <string name="month_day_year">%-e %B %Y р.</string>
     <string name="time_of_day">%H:%M:%S</string>
-    <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%-e %b %Y</string>
+    <string name="date_and_time">%-e %b %Y р., %H:%M:%S</string>
+    <string name="date_time">%1$s, %2$s</string>
+    <string name="time_date">%3$s, %1$s</string>
+    <string name="abbrev_month_day_year">%-e %b %Y р.</string>
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
-    <string name="month_year">%-B %Y</string>
+    <string name="month_year">%-B %Y р.</string>
     <string name="abbrev_month_day">%-e %b</string>
     <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%-b %Y</string>
+    <string name="abbrev_month_year">%-b %Y р.</string>
     <string name="time1_time2">%1$s – %2$s</string>
     <string name="date1_date2">%2$s – %5$s</string>
     <string name="numeric_md1_md2">%3$s.%2$s – %8$s.%7$s</string>
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s – %6$s, %8$s.%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s – %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s – %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s – %10$s %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s – %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s – %10$s %6$s, %8$s.%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s – %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s – %6$s %4$s, %5$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s.%2$s.%4$s, %5$s – %6$s, %8$s.%7$s.%9$s, %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%3$s.%2$s, %5$s – %8$s.%7$s, %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s.%2$s, %5$s – %6$s, %8$s.%7$s, %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%3$s.%2$s.%4$s, %5$s – %8$s.%7$s.%9$s, %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s – %4$s, %5$s, %6$s</string>
     <string name="wday1_date1_wday2_date2">%1$s, %2$s – %4$s, %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="date1_time1_date2_time2">%2$s, %3$s – %5$s, %6$s</string>
+    <string name="time_wday_date">%2$s, %3$s, %1$s</string>
     <string name="wday_date">%2$s, %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
+    <string name="time_wday">%2$s, %1$s</string>
     <string name="same_year_md1_md2">%3$s %2$s – %8$s %7$s</string>
     <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s – %6$s, %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s – %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s – %10$s %6$s, %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s – %10$s %6$s, %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s – %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s – %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s – %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s–%8$s %2$s</string>
+    <string name="same_year_md1_time1_md2_time2">%3$s %2$s, %5$s – %8$s %7$s, %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%3$s %2$s, %5$s – %8$s %7$s, %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s – %6$s, %8$s %7$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s – %6$s, %8$s %7$s, %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s р., %5$s – %8$s %7$s %9$s р., %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s р., %5$s – %8$s %7$s %9$s р., %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s р., %5$s – %6$s, %8$s %7$s %9$s р., %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s р., %5$s – %6$s, %8$s %7$s %9$s р., %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s р. – %6$s, %8$s %7$s %9$s р.</string>
+    <string name="same_month_md1_md2">%3$s – %8$s %2$s</string>
     <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s – %6$s, %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s %2$s – %8$s %7$s %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s – %6$s, %8$s %7$s %9$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s %2$s – %8$s %7$s %9$s р.</string>
+    <string name="same_month_mdy1_mdy2">%3$s – %8$s %2$s %9$s р.</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s – %6$s, %8$s %7$s %9$s р.</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/donottranslate-cldr.xml b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
index 6d52d70..5077e94 100644
--- a/core/res/res/values-zh-rCN/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
@@ -1,57 +1,57 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">一月</string>
-    <string name="month_long_standalone_february">二月</string>
-    <string name="month_long_standalone_march">三月</string>
-    <string name="month_long_standalone_april">四月</string>
-    <string name="month_long_standalone_may">五月</string>
-    <string name="month_long_standalone_june">六月</string>
-    <string name="month_long_standalone_july">七月</string>
-    <string name="month_long_standalone_august">八月</string>
-    <string name="month_long_standalone_september">九月</string>
-    <string name="month_long_standalone_october">十月</string>
-    <string name="month_long_standalone_november">十一月</string>
-    <string name="month_long_standalone_december">十二月</string>
+    <string name="month_long_standalone_january">1 月</string>
+    <string name="month_long_standalone_february">2 月</string>
+    <string name="month_long_standalone_march">3 月</string>
+    <string name="month_long_standalone_april">4 月</string>
+    <string name="month_long_standalone_may">5 月</string>
+    <string name="month_long_standalone_june">6 月</string>
+    <string name="month_long_standalone_july">7 月</string>
+    <string name="month_long_standalone_august">8 月</string>
+    <string name="month_long_standalone_september">9 月</string>
+    <string name="month_long_standalone_october">10 月</string>
+    <string name="month_long_standalone_november">11 月</string>
+    <string name="month_long_standalone_december">12 月</string>
 
-    <string name="month_long_january">1月</string>
-    <string name="month_long_february">2月</string>
-    <string name="month_long_march">3月</string>
-    <string name="month_long_april">4月</string>
-    <string name="month_long_may">5月</string>
-    <string name="month_long_june">6月</string>
-    <string name="month_long_july">7月</string>
-    <string name="month_long_august">8月</string>
-    <string name="month_long_september">9月</string>
-    <string name="month_long_october">10月</string>
-    <string name="month_long_november">11月</string>
-    <string name="month_long_december">12月</string>
+    <string name="month_long_january">1 月</string>
+    <string name="month_long_february">2 月</string>
+    <string name="month_long_march">3 月</string>
+    <string name="month_long_april">4 月</string>
+    <string name="month_long_may">5 月</string>
+    <string name="month_long_june">6 月</string>
+    <string name="month_long_july">7 月</string>
+    <string name="month_long_august">8 月</string>
+    <string name="month_long_september">9 月</string>
+    <string name="month_long_october">10 月</string>
+    <string name="month_long_november">11 月</string>
+    <string name="month_long_december">12 月</string>
 
-    <string name="month_medium_january">1月</string>
-    <string name="month_medium_february">2月</string>
-    <string name="month_medium_march">3月</string>
-    <string name="month_medium_april">4月</string>
-    <string name="month_medium_may">5月</string>
-    <string name="month_medium_june">6月</string>
-    <string name="month_medium_july">7月</string>
-    <string name="month_medium_august">8月</string>
-    <string name="month_medium_september">9月</string>
-    <string name="month_medium_october">10月</string>
-    <string name="month_medium_november">11月</string>
-    <string name="month_medium_december">12月</string>
+    <string name="month_medium_january">1 月</string>
+    <string name="month_medium_february">2 月</string>
+    <string name="month_medium_march">3 月</string>
+    <string name="month_medium_april">4 月</string>
+    <string name="month_medium_may">5 月</string>
+    <string name="month_medium_june">6 月</string>
+    <string name="month_medium_july">7 月</string>
+    <string name="month_medium_august">8 月</string>
+    <string name="month_medium_september">9 月</string>
+    <string name="month_medium_october">10 月</string>
+    <string name="month_medium_november">11 月</string>
+    <string name="month_medium_december">12 月</string>
 
-    <string name="month_shortest_january">1月</string>
-    <string name="month_shortest_february">2月</string>
-    <string name="month_shortest_march">3月</string>
-    <string name="month_shortest_april">4月</string>
-    <string name="month_shortest_may">5月</string>
-    <string name="month_shortest_june">6月</string>
-    <string name="month_shortest_july">7月</string>
-    <string name="month_shortest_august">8月</string>
-    <string name="month_shortest_september">9月</string>
-    <string name="month_shortest_october">10月</string>
-    <string name="month_shortest_november">11月</string>
-    <string name="month_shortest_december">12月</string>
+    <string name="month_shortest_january">1 月</string>
+    <string name="month_shortest_february">2 月</string>
+    <string name="month_shortest_march">3 月</string>
+    <string name="month_shortest_april">4 月</string>
+    <string name="month_shortest_may">5 月</string>
+    <string name="month_shortest_june">6 月</string>
+    <string name="month_shortest_july">7 月</string>
+    <string name="month_shortest_august">8 月</string>
+    <string name="month_shortest_september">9 月</string>
+    <string name="month_shortest_october">10 月</string>
+    <string name="month_shortest_november">11 月</string>
+    <string name="month_shortest_december">12 月</string>
 
     <string name="day_of_week_long_sunday">星期日</string>
     <string name="day_of_week_long_monday">星期一</string>
@@ -92,56 +92,56 @@
     <string name="tomorrow">明天</string>
 
     <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%p%-l:%M</string>
-    <string name="hour_minute_cap_ampm">%p%-l:%M</string>
-    <string name="twelve_hour_time_format">ah:mm</string>
+    <string name="hour_minute_ampm">%p %-l:%M</string>
+    <string name="hour_minute_cap_ampm">%p %-l:%M</string>
+    <string name="twelve_hour_time_format">a h:mm</string>
     <string name="twenty_four_hour_time_format">H:mm</string>
     <string name="numeric_date">%Y-%-m-%-e</string>
     <string name="numeric_date_format">yyyy-M-d</string>
     <string name="numeric_date_template">"%s-%s-%s"</string>
-    <string name="month_day_year">%Y年%-m月%-e日</string>
-    <string name="time_of_day">%p%I:%M:%S</string>
-    <string name="date_and_time">%p%I:%M:%S %Y-%-m-%-e</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
+    <string name="month_day_year">%Y 年 %-m 月 %-e 日</string>
+    <string name="time_of_day">%p %I:%M:%S</string>
+    <string name="date_and_time">%Y 年 %-m 月 %-e 日%p %I:%M:%S</string>
+    <string name="date_time">%1$s %2$s</string>
+    <string name="time_date">%3$s %1$s</string>
     <string name="abbrev_month_day_year">%Y-%-m-%-e</string>
-    <string name="month_day">%B%-e日</string>
+    <string name="month_day">%B %-e 日</string>
     <string name="month">%-B</string>
-    <string name="month_year">%Y年%B</string>
-    <string name="abbrev_month_day">%b%-e日</string>
+    <string name="month_year">%Y 年 %B</string>
+    <string name="abbrev_month_day">%b %-e 日</string>
     <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y年%b</string>
-    <string name="time1_time2">%1$s–%2$s</string>
-    <string name="date1_date2">%2$s–%5$s</string>
-    <string name="numeric_md1_md2">%2$s-%3$s至%7$s-%8$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%2$s-%3$s%1$s至%7$s-%8$s%6$s</string>
-    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s至%9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s-%2$s-%3$s%1$s至%9$s-%7$s-%8$s%6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s月%3$s日,%1$s–%10$s %9$s年%7$s月%8$s日,%6$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s–%10$s %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s-%3$s%1$s–%10$s %7$s-%8$s%6$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s–%10$s %9$s-%7$s-%8$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s%1$s–%6$s %5$s%4$s</string>
-    <string name="wday1_date1_wday2_date2">%2$s%1$s–%5$s%4$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s–%6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s%2$s</string>
+    <string name="abbrev_month_year">%Y 年 %b</string>
+    <string name="time1_time2">%1$s – %2$s</string>
+    <string name="date1_date2">%2$s – %5$s</string>
+    <string name="numeric_md1_md2">%2$s 月 %3$s 日 - %7$s 月 %8$s 日</string>
+    <string name="numeric_wday1_md1_wday2_md2">%2$s 月 %3$s 日%1$s - %7$s 月 %8$s 日%6$s</string>
+    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s - %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s-%2$s-%3$s %1$s - %9$s-%7$s-%8$s %6$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%4$s-%2$s-%3$s %5$s %1$s – %9$s-%7$s-%8$s %10$s %6$s</string>
+    <string name="numeric_md1_time1_md2_time2">%2$s 月 %3$s 日 %5$s – %7$s 月 %8$s 日 %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%2$s 月 %3$s 日 %5$s %1$s – %7$s 月 %8$s 日 %10$s %6$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%4$s-%2$s-%3$s %5$s – %9$s-%7$s-%8$s %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%2$s %3$s %1$s – %5$s %6$s %4$s</string>
+    <string name="wday1_date1_wday2_date2">%2$s%1$s – %5$s%4$s</string>
+    <string name="date1_time1_date2_time2">%2$s %3$s – %5$s %6$s</string>
+    <string name="time_wday_date">%3$s %1$s %2$s</string>
     <string name="wday_date">%3$s%2$s</string>
     <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%2$s%3$s日–%7$s%8$s日</string>
-    <string name="same_year_wday1_md1_wday2_md2">%2$s%3$s日%1$s–%7$s%8$s日%6$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %2$s%3$s日–%10$s %7$s%8$s日</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %2$s%3$s日–%10$s %7$s%8$s日</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s%3$s日%1$s–%10$s %7$s%8$s日%6$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s%3$s日%1$s–%10$s %7$s%8$s日%6$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s年%2$s%3$s日–%10$s %9$s年%7$s%8$s日</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s年%2$s%3$s日–%10$s %9$s年%7$s%8$s日</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日%1$s–%9$s年%7$s%8$s日%6$s</string>
-    <string name="same_month_md1_md2">%2$s%3$s日至%8$s日</string>
-    <string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日%1$s–%7$s%8$s日%6$s</string>
-    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日至%7$s%8$s日</string>
-    <string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日至%8$s日</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日%1$s至%7$s%8$s日%6$s</string>
+    <string name="same_year_md1_md2">%2$s %3$s 日 – %7$s %8$s 日</string>
+    <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s 日%1$s – %7$s %8$s 日%6$s</string>
+    <string name="same_year_md1_time1_md2_time2">%2$s %3$s 日 %5$s – %7$s %8$s 日 %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%2$s %3$s 日 %5$s – %7$s %8$s 日 %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%2$s %3$s 日 %5$s %1$s – %7$s %8$s 日 %10$s %6$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%2$s %3$s 日 %1$s %5$s – %7$s %8$s 日 %6$s %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%4$s 年 %2$s %3$s 日 %5$s – %9$s 年 %7$s %8$s 日 %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%4$s 年 %2$s %3$s 日 %5$s – %9$s 年 %7$s %8$s 日 %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%4$s 年 %2$s %3$s 日 %5$s %1$s – %9$s 年 %7$s %8$s 日 %10$s %6$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%4$s 年 %2$s %3$s 日 %5$s %1$s – %9$s 年 %7$s %8$s 日 %10$s %6$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s 年 %2$s %3$s 日%1$s – %9$s 年 %7$s %8$s 日%6$s</string>
+    <string name="same_month_md1_md2">%2$s %3$s - %8$s 日</string>
+    <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s 日%1$s – %7$s %8$s 日%6$s</string>
+    <string name="same_year_mdy1_mdy2">%9$s 年 %2$s %3$s 日 - %7$s %8$s 日</string>
+    <string name="same_month_mdy1_mdy2">%9$s 年 %2$s %3$s - %8$s 日</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s 年 %2$s %3$s 日%1$s - %7$s %8$s 日%6$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 0c651c9..6741b3b 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"无法访问该文件。"</string>
     <string name="httpErrorFileNotFound">"找不到请求的文件。"</string>
     <string name="httpErrorTooManyRequests">"正在处理的请求太多,请稍后重试。"</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"同步"</string>
     <string name="contentServiceSyncNotificationTitle">"同步"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"太多<xliff:g id="CONTENT_TYPE">%s</xliff:g>删除项。"</string>
diff --git a/core/res/res/values-zh-rTW/donottranslate-cldr.xml b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
index 6d52d70..3e1acf1 100644
--- a/core/res/res/values-zh-rTW/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
@@ -1,57 +1,57 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">一月</string>
-    <string name="month_long_standalone_february">二月</string>
-    <string name="month_long_standalone_march">三月</string>
-    <string name="month_long_standalone_april">四月</string>
-    <string name="month_long_standalone_may">五月</string>
-    <string name="month_long_standalone_june">六月</string>
-    <string name="month_long_standalone_july">七月</string>
-    <string name="month_long_standalone_august">八月</string>
-    <string name="month_long_standalone_september">九月</string>
-    <string name="month_long_standalone_october">十月</string>
-    <string name="month_long_standalone_november">十一月</string>
-    <string name="month_long_standalone_december">十二月</string>
+    <string name="month_long_standalone_january">1 月</string>
+    <string name="month_long_standalone_february">2 月</string>
+    <string name="month_long_standalone_march">3 月</string>
+    <string name="month_long_standalone_april">4 月</string>
+    <string name="month_long_standalone_may">5 月</string>
+    <string name="month_long_standalone_june">6 月</string>
+    <string name="month_long_standalone_july">7 月</string>
+    <string name="month_long_standalone_august">8 月</string>
+    <string name="month_long_standalone_september">9 月</string>
+    <string name="month_long_standalone_october">10 月</string>
+    <string name="month_long_standalone_november">11 月</string>
+    <string name="month_long_standalone_december">12 月</string>
 
-    <string name="month_long_january">1月</string>
-    <string name="month_long_february">2月</string>
-    <string name="month_long_march">3月</string>
-    <string name="month_long_april">4月</string>
-    <string name="month_long_may">5月</string>
-    <string name="month_long_june">6月</string>
-    <string name="month_long_july">7月</string>
-    <string name="month_long_august">8月</string>
-    <string name="month_long_september">9月</string>
-    <string name="month_long_october">10月</string>
-    <string name="month_long_november">11月</string>
-    <string name="month_long_december">12月</string>
+    <string name="month_long_january">1 月</string>
+    <string name="month_long_february">2 月</string>
+    <string name="month_long_march">3 月</string>
+    <string name="month_long_april">4 月</string>
+    <string name="month_long_may">5 月</string>
+    <string name="month_long_june">6 月</string>
+    <string name="month_long_july">7 月</string>
+    <string name="month_long_august">8 月</string>
+    <string name="month_long_september">9 月</string>
+    <string name="month_long_october">10 月</string>
+    <string name="month_long_november">11 月</string>
+    <string name="month_long_december">12 月</string>
 
-    <string name="month_medium_january">1月</string>
-    <string name="month_medium_february">2月</string>
-    <string name="month_medium_march">3月</string>
-    <string name="month_medium_april">4月</string>
-    <string name="month_medium_may">5月</string>
-    <string name="month_medium_june">6月</string>
-    <string name="month_medium_july">7月</string>
-    <string name="month_medium_august">8月</string>
-    <string name="month_medium_september">9月</string>
-    <string name="month_medium_october">10月</string>
-    <string name="month_medium_november">11月</string>
-    <string name="month_medium_december">12月</string>
+    <string name="month_medium_january">1 月</string>
+    <string name="month_medium_february">2 月</string>
+    <string name="month_medium_march">3 月</string>
+    <string name="month_medium_april">4 月</string>
+    <string name="month_medium_may">5 月</string>
+    <string name="month_medium_june">6 月</string>
+    <string name="month_medium_july">7 月</string>
+    <string name="month_medium_august">8 月</string>
+    <string name="month_medium_september">9 月</string>
+    <string name="month_medium_october">10 月</string>
+    <string name="month_medium_november">11 月</string>
+    <string name="month_medium_december">12 月</string>
 
-    <string name="month_shortest_january">1月</string>
-    <string name="month_shortest_february">2月</string>
-    <string name="month_shortest_march">3月</string>
-    <string name="month_shortest_april">4月</string>
-    <string name="month_shortest_may">5月</string>
-    <string name="month_shortest_june">6月</string>
-    <string name="month_shortest_july">7月</string>
-    <string name="month_shortest_august">8月</string>
-    <string name="month_shortest_september">9月</string>
-    <string name="month_shortest_october">10月</string>
-    <string name="month_shortest_november">11月</string>
-    <string name="month_shortest_december">12月</string>
+    <string name="month_shortest_january">1 月</string>
+    <string name="month_shortest_february">2 月</string>
+    <string name="month_shortest_march">3 月</string>
+    <string name="month_shortest_april">4 月</string>
+    <string name="month_shortest_may">5 月</string>
+    <string name="month_shortest_june">6 月</string>
+    <string name="month_shortest_july">7 月</string>
+    <string name="month_shortest_august">8 月</string>
+    <string name="month_shortest_september">9 月</string>
+    <string name="month_shortest_october">10 月</string>
+    <string name="month_shortest_november">11 月</string>
+    <string name="month_shortest_december">12 月</string>
 
     <string name="day_of_week_long_sunday">星期日</string>
     <string name="day_of_week_long_monday">星期一</string>
@@ -92,56 +92,56 @@
     <string name="tomorrow">明天</string>
 
     <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%p%-l:%M</string>
-    <string name="hour_minute_cap_ampm">%p%-l:%M</string>
-    <string name="twelve_hour_time_format">ah:mm</string>
+    <string name="hour_minute_ampm">%p %-l:%M</string>
+    <string name="hour_minute_cap_ampm">%p %-l:%M</string>
+    <string name="twelve_hour_time_format">a h:mm</string>
     <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%Y-%-m-%-e</string>
-    <string name="numeric_date_format">yyyy-M-d</string>
-    <string name="numeric_date_template">"%s-%s-%s"</string>
-    <string name="month_day_year">%Y年%-m月%-e日</string>
-    <string name="time_of_day">%p%I:%M:%S</string>
-    <string name="date_and_time">%p%I:%M:%S %Y-%-m-%-e</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%Y-%-m-%-e</string>
-    <string name="month_day">%B%-e日</string>
+    <string name="numeric_date">%Y/%-m/%-e</string>
+    <string name="numeric_date_format">yyyy/M/d</string>
+    <string name="numeric_date_template">"%s/%s/%s"</string>
+    <string name="month_day_year">%Y 年 %-m 月 %-e 日</string>
+    <string name="time_of_day">%p %I:%M:%S</string>
+    <string name="date_and_time">%Y/%-m/%-e %p %I:%M:%S</string>
+    <string name="date_time">%1$s %2$s</string>
+    <string name="time_date">%3$s %1$s</string>
+    <string name="abbrev_month_day_year">%Y/%-m/%-e</string>
+    <string name="month_day">%B %-e 日</string>
     <string name="month">%-B</string>
-    <string name="month_year">%Y年%B</string>
-    <string name="abbrev_month_day">%b%-e日</string>
+    <string name="month_year">%Y 年 %B</string>
+    <string name="abbrev_month_day">%b %-e 日</string>
     <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y年%b</string>
-    <string name="time1_time2">%1$s–%2$s</string>
-    <string name="date1_date2">%2$s–%5$s</string>
-    <string name="numeric_md1_md2">%2$s-%3$s至%7$s-%8$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%2$s-%3$s%1$s至%7$s-%8$s%6$s</string>
-    <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s至%9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s-%2$s-%3$s%1$s至%9$s-%7$s-%8$s%6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s月%3$s日,%1$s–%10$s %9$s年%7$s月%8$s日,%6$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s–%10$s %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s-%3$s%1$s–%10$s %7$s-%8$s%6$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s–%10$s %9$s-%7$s-%8$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s%1$s–%6$s %5$s%4$s</string>
-    <string name="wday1_date1_wday2_date2">%2$s%1$s–%5$s%4$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s–%6$s %5$s</string>
-    <string name="time_wday_date">%1$s %3$s%2$s</string>
+    <string name="abbrev_month_year">%Y 年 %b</string>
+    <string name="time1_time2">%1$s - %2$s</string>
+    <string name="date1_date2">%2$s至 %5$s</string>
+    <string name="numeric_md1_md2">%2$s/%3$s 至 %7$s/%8$s</string>
+    <string name="numeric_wday1_md1_wday2_md2">%2$s/%3$s %1$s至 %7$s/%8$s %6$s</string>
+    <string name="numeric_mdy1_mdy2">%4$s/%2$s/%3$s 至 %9$s/%7$s/%8$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s/%2$s/%3$s %1$s至 %9$s/%7$s/%8$s %6$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%4$s 年 %2$s 月 %3$s 日%1$s %5$s 至 %9$s 年 %7$s 月 %8$s 日%6$s %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%2$s/%3$s %5$s 至 %7$s/%8$s %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%2$s/%3$s %1$s %5$s 至 %7$s/%8$s %6$s %10$s</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%4$s/%2$s/%3$s %5$s 至 %9$s/%7$s/%8$s %10$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%2$s%1$s %3$s 至 %5$s%4$s %6$s</string>
+    <string name="wday1_date1_wday2_date2">%2$s%1$s至 %5$s%4$s</string>
+    <string name="date1_time1_date2_time2">%2$s %3$s 至 %5$s %6$s</string>
+    <string name="time_wday_date">%3$s%2$s %1$s</string>
     <string name="wday_date">%3$s%2$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%2$s%3$s日–%7$s%8$s日</string>
-    <string name="same_year_wday1_md1_wday2_md2">%2$s%3$s日%1$s–%7$s%8$s日%6$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %2$s%3$s日–%10$s %7$s%8$s日</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %2$s%3$s日–%10$s %7$s%8$s日</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s%3$s日%1$s–%10$s %7$s%8$s日%6$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s%3$s日%1$s–%10$s %7$s%8$s日%6$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s年%2$s%3$s日–%10$s %9$s年%7$s%8$s日</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s年%2$s%3$s日–%10$s %9$s年%7$s%8$s日</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日%1$s–%9$s年%7$s%8$s日%6$s</string>
-    <string name="same_month_md1_md2">%2$s%3$s日至%8$s日</string>
-    <string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日%1$s–%7$s%8$s日%6$s</string>
-    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日至%7$s%8$s日</string>
-    <string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日至%8$s日</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日%1$s至%7$s%8$s日%6$s</string>
+    <string name="time_wday">%2$s %1$s</string>
+    <string name="same_year_md1_md2">%2$s %3$s 日至 %7$s %8$s 日</string>
+    <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s 日%1$s至 %7$s %8$s 日%6$s</string>
+    <string name="same_year_md1_time1_md2_time2">%2$s %3$s 日 %5$s 至 %7$s %8$s 日 %10$s</string>
+    <string name="same_month_md1_time1_md2_time2">%2$s %3$s 日 %5$s 至 %7$s %8$s 日 %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%2$s %3$s 日%1$s %5$s 至 %7$s %8$s 日%6$s %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%2$s %3$s 日%1$s %5$s 至 %7$s %8$s 日%6$s %10$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%4$s 年 %2$s %3$s 日 %5$s 至 %9$s 年 %7$s %8$s 日 %10$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%4$s 年 %2$s %3$s 日 %5$s 至 %9$s 年 %7$s %8$s 日 %10$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%4$s 年 %2$s %3$s 日%1$s %5$s 至 %9$s 年 %7$s %8$s 日%6$s %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%4$s 年 %2$s %3$s 日%1$s %5$s 至 %9$s 年 %7$s %8$s 日%6$s %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s 年 %2$s %3$s 日%1$s至 %9$s 年 %7$s %8$s 日%6$s</string>
+    <string name="same_month_md1_md2">%2$s %3$s 日至 %8$s 日</string>
+    <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s 日%1$s至 %7$s %8$s 日%6$s</string>
+    <string name="same_year_mdy1_mdy2">%9$s 年 %2$s %3$s 日至 %7$s %8$s 日</string>
+    <string name="same_month_mdy1_mdy2">%9$s 年 %2$s %3$s 日至 %8$s 日</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s 年 %2$s %3$s 日%1$s至 %7$s %8$s 日%6$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index a611532..f355a71 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"無法存取此檔案。"</string>
     <string name="httpErrorFileNotFound">"找不到要求的檔案。"</string>
     <string name="httpErrorTooManyRequests">"太多執行要求。請稍後再試一次。"</string>
-    <string name="certificateSaved">"憑證已儲存在系統的金鑰存放區。"</string>
     <string name="contentServiceSync">"同步處理"</string>
     <string name="contentServiceSyncNotificationTitle">"同步處理"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"同時刪除太多 <xliff:g id="CONTENT_TYPE">%s</xliff:g>。"</string>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 75568e1..48b565f 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -827,28 +827,6 @@
         <attr name="name" />
     </declare-styleable>
     
-    <!-- The <code>supports-density</code> specifies a screen density that this
-         package supports. Application can specify multiple densities it supports.
-         <p>This appears as a child tag of the
-         {@link #AndroidManifest manifest} tag. -->
-    <declare-styleable name="AndroidManifestSupportsDensity" parent="AndroidManifest">
-        <!-- Required value of the density in dip (device independent pixel).
-             You should use one of the pre-defined constants for the standard
-             screen densities defined here.
-        -->
-        <attr name="density" format="integer">
-            <!-- A low density screen, such as a QVGA or WQVGA screen in a
-                 typical hand-held phone.  The constant for this is 120. -->
-            <enum name="low" value="120" />
-            <!-- A medium density screen, such as an HVGA screen in a
-                 typical hand-held phone.  The constant for this is 160. -->
-            <enum name="medium" value="160" />
-            <!-- A high density screen, such as a VGA or WVGA screen in a
-                 typical hand-held phone.  The constant for this is 240. -->
-            <enum name="high" value="240" />
-        </attr>
-    </declare-styleable>
-
     <!-- The <code>supports-screens</code> specifies the screen dimensions an
          application supports.  By default a modern application supports all
          screen sizes and must explicitly disable certain screen sizes here;
@@ -892,6 +870,11 @@
              set for you automatically based on whether you are targeting
              a newer platform that supports more screens. -->
         <attr name="resizeable" format="boolean" />
+        <!-- Indicates whether the application can accommodate any screen
+             density.  Older applications are assumed to not be able to,
+             new ones able to.  You can explicitly supply your abilities
+             here. -->
+        <attr name="anyDensity" format="boolean" />
     </declare-styleable>
 
     <!-- Private tag to declare system protected broadcast actions.
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e99f8be..f8dd4c1 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1093,7 +1093,7 @@
 
   <public type="attr" name="tension" id="0x0101026a" />
   <public type="attr" name="extraTension" />
-  <public type="attr" name="density" />
+  <public type="attr" name="anyDensity" />
   <public type="attr" name="searchSuggestThreshold" />
   <public type="attr" name="includeInGlobalSearch" />
   <public type="attr" name="onClick" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3f749e8..0e848398 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -228,8 +228,6 @@
     <string name="httpErrorFileNotFound">The requested file was not found.</string>
     <!-- Displayed when a request failed because there are too many requests right now. -->
     <string name="httpErrorTooManyRequests">Too many requests are being processed. Try again later.</string>
-    <!-- Displayed a toast that a certificate is saved in the keystore -->
-    <string name="certificateSaved">The certificate is saved in the system\'s key store.</string>
 
     <!-- Account notifications --> <skip />
     <!-- A notification is shown when the AccountManager is unable to
@@ -809,7 +807,7 @@
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_readFrameBuffer">read frame buffer</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_readFrameBuffer">Allows application to 
+    <string name="permdesc_readFrameBuffer">Allows application to
         read the content of the frame buffer.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -970,12 +968,40 @@
         the phone\'s time zone.</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_accountManagerService">act as the AccountManagerService</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_accountManagerService">Allows an
+    application to make calls to AccountAuthenticators</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_getAccounts">discover known accounts</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_getAccounts">Allows an application to get
       the list of accounts known by the phone.</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_authenticateAccounts">act as an account authenticator</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_authenticateAccounts">Allows an application
+    to use the account authenticator capabilities of the
+    AccountManager, including creating accounts and getting and
+    setting their passwords.</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_manageAccounts">manage the accounts list</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_manageAccounts">Allows an application to
+    perform operations like adding, and removing accounts and deleting
+    their password.</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_useCredentials">use the authentication
+    credentials of an account</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_useCredentials">Allows an application to
+    request authentication tokens.</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_accessNetworkState">view network state</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_accessNetworkState">Allows an application to view
@@ -1797,7 +1823,7 @@
     <string name="adb_active_notification_title">USB debugging connected</string>
     <!-- Message of notification shown when ADB is actively connected to the phone. -->
     <string name="adb_active_notification_message">A computer is connected to your phone.</string>
-    
+
     <!-- Used to replace %s in urls retreived from the signin server with locales.  For Some        -->
     <!-- devices we don't support all the locales we ship to and need to replace the '%s' with a    -->
     <!-- locale string based on mcc values.  By default (0-length string) we don't replace the %s   -->
@@ -2048,4 +2074,19 @@
      <!-- Title for the unselected state of a CompoundButton. -->
      <string name="accessibility_compound_button_unselected">not checked</string>
 
+     <string name="grant_credentials_permission_message_desc">The
+     listed applications are requesting permission to access the login credentials for account %s from
+     %s. Do you wish to grant this permission? If so then your answer will be remembered and you will not be prompted
+     again.</string>
+
+     <string name="grant_credentials_permission_message_with_authtokenlabel_desc">The
+     listed applications are requesting permission to access the %s login credentials for account %s from
+     %s. Do you wish to grant this permission? If so then your answer will be remembered and you will not be prompted
+     again.</string>
+
+     <string name="allow">Allow</string>
+     <string name="deny">Deny</string>
+     <string name="permission_request_notification_title">Permission Requested</string>
+     <string name="permission_request_notification_subtitle">for account %s</string>
+
 </resources>
diff --git a/data/sounds/AudioPackage2.mk b/data/sounds/AudioPackage2.mk
index 649787e..5dacc70 100644
--- a/data/sounds/AudioPackage2.mk
+++ b/data/sounds/AudioPackage2.mk
@@ -23,7 +23,6 @@
 	$(LOCAL_PATH)/Ring_Digital_02.ogg:system/media/audio/ringtones/Ring_Digital_02.ogg \
 	$(LOCAL_PATH)/Ring_Synth_04.ogg:system/media/audio/ringtones/Ring_Synth_04.ogg \
 	$(LOCAL_PATH)/Ring_Synth_02.ogg:system/media/audio/ringtones/Ring_Synth_02.ogg \
-	$(LOCAL_PATH)/Silence.ogg:system/media/audio/ringtones/notifications/Silence.ogg \
 	$(LOCAL_PATH)/newwavelabs/BeatPlucker.ogg:system/media/audio/ringtones/BeatPlucker.ogg \
 	$(LOCAL_PATH)/newwavelabs/BentleyDubs.ogg:system/media/audio/ringtones/BentleyDubs.ogg \
 	$(LOCAL_PATH)/newwavelabs/BirdLoop.ogg:system/media/audio/ringtones/BirdLoop.ogg \
diff --git a/data/sounds/OriginalAudio.mk b/data/sounds/OriginalAudio.mk
index fc1e921..291f0b6 100644
--- a/data/sounds/OriginalAudio.mk
+++ b/data/sounds/OriginalAudio.mk
@@ -22,7 +22,6 @@
 	$(LOCAL_PATH)/Ring_Digital_02.ogg:system/media/audio/ringtones/Ring_Digital_02.ogg \
 	$(LOCAL_PATH)/Ring_Synth_04.ogg:system/media/audio/ringtones/Ring_Synth_04.ogg \
 	$(LOCAL_PATH)/Ring_Synth_02.ogg:system/media/audio/ringtones/Ring_Synth_02.ogg \
-	$(LOCAL_PATH)/Silence.ogg:system/media/audio/ringtones/notifications/Silence.ogg \
 	$(LOCAL_PATH)/newwavelabs/BeatPlucker.ogg:system/media/audio/ringtones/BeatPlucker.ogg \
 	$(LOCAL_PATH)/newwavelabs/BentleyDubs.ogg:system/media/audio/ringtones/BentleyDubs.ogg \
 	$(LOCAL_PATH)/newwavelabs/BirdLoop.ogg:system/media/audio/ringtones/BirdLoop.ogg \
diff --git a/data/sounds/Silence.ogg b/data/sounds/Silence.ogg
deleted file mode 100644
index 6d78907..0000000
--- a/data/sounds/Silence.ogg
+++ /dev/null
Binary files differ
diff --git a/docs/html/community/index.jd b/docs/html/community/index.jd
index 91c54aa..eb5887a 100644
--- a/docs/html/community/index.jd
+++ b/docs/html/community/index.jd
@@ -9,7 +9,7 @@
 <p class="note"><strong>Note:</strong> If you are seeking discussion about Android source code (not application development),
 then please refer to the <a href="http://source.android.com/discuss">Open Source Project Mailing lists</a>.</p>
 
-<p style="margin-bottom".5em"><strong>Contents</strong></p>
+<p style="margin-bottom:.5em"><strong>Contents</strong></p>
 <ol class="toc">
   <li><a href="#BeforeYouPost">Before you post</a></li>
   <li><a href="#ApplicationDeveloperLists">Application developer mailing lists</a></li>
diff --git a/docs/html/guide/appendix/faq/commontasks.jd b/docs/html/guide/appendix/faq/commontasks.jd
index 259b5d1..e88a867 100644
--- a/docs/html/guide/appendix/faq/commontasks.jd
+++ b/docs/html/guide/appendix/faq/commontasks.jd
@@ -56,7 +56,7 @@
 to understand the basics of how an Android application works.</p> 
 
 <p>You should also take a look at the ApiDemos application and the other sample
-applications included in the SDK, in the <code>&lt;sdk&gt;/samples/ 
+applications included in the SDK, in the <code>&lt;sdk&gt;/samples/</code>
 folder in the SDK.</p>
 
 <p>Finally, a great way to started with Android development in Eclipse is to
@@ -281,6 +281,15 @@
 <pre>//Hide the title bar
 requestWindowFeature(Window.FEATURE_NO_TITLE);
 </pre>
+<p>A better way to achieve the same end is to specify a theme in your Android
+Manifest file:</p>
+<pre>&lt;application android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar"&gt;
+</pre>
+<p>This is preferable because it tells the system not to show a title bar while
+your application is starting up. With the explicit method call, your application
+will have a title bar visible to the user until <code>onCreate</code> runs.</p>
+<p>(Note that this can be applied to either the <code>&lt;application&gt;</code>
+tag or to individual <code>&lt;activity&gt;</code> tags.)</p>
 <a name="localhostalias" id="localhostalias"></a><h2>Referring to localhost from the emulated environment</h2>
 <p>
 If you need to refer to your host computer's <em>localhost</em>, such as when you 
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index c00f312..2c42e78 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -137,7 +137,7 @@
       <li>If you're developing on Mac OS X, it just works. Skip this step.</li>
       <li>If you're developing on Ubuntu Linux, you need to add a rules file:
         <ol>
-          <li>Login as root and create this file: <code>/etc/udev/rules.d/50-android.rules</code>.
+          <li>Login as root and create this file: <code>/etc/udev/rules.d/51-android.rules</code>.
             <p>For Gusty/Hardy, edit the file to read: <br/>
               <code>SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"</code></p>
 
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index da4a2c3..2127187 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -1,84 +1,175 @@
+<?cs # Table of contents for Dev Guide. 
+
+       For each document available in translation, add an localized title to this TOC. 
+       Do not add localized title for docs not available in translation.
+       Below are template spans for adding localized doc titles. Please ensure that
+       localized titles are added in the language order specified below.
+?>
 <ul>
 
-<li><h2>Android Basics</h2>
+  <li>
+    <h2><span class="en">Android Basics</span>
+        <span class="de">Einführung in Android</span>
+        <span class="es">Información básica sobre Android</span>
+        <span class="fr">Présentation d'Android</span>
+        <span class="it">Nozioni di base su Android</span>
+        <span class="ja">Android の基本</span>
+        <span class="zh-CN">Android 基础知识</span>
+        <span class="zh-TW">Android 簡介</span>
+    </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>guide/basics/what-is-android.html">What Is Android?</a></li>
-<!--  <li><a style="color:gray;">The Android SDK</a></li> -->
-<!--  <li><a style="color:gray;">Walkthrough for Developers</a></li> -->
+      <li><a href="<?cs var:toroot ?>guide/basics/what-is-android.html">
+        <span class="en">What Is Android?</span>
+        <span class="de">Was ist Android?</span>
+        <span class="es">¿Qué es Android?</span>
+        <span class="fr">Qu'est-ce qu'Android&nbsp;?</span>
+        <span class="it">Che cos'è Android?</span>
+        <span class="ja">Android とは</span>
+        <span class="zh-CN">Android 是什么?</span>
+        <span class="zh-TW">什麼是 Android?</span>
+          </a></li>
+  <!--  <li><a style="color:gray;">The Android SDK</a></li> -->
+  <!--  <li><a style="color:gray;">Walkthrough for Developers</a></li> -->
       <!-- quick overview of what it's like to develop on Android -->
     </ul>
-</li>
+  </li>
+  
+  <li>
+    <h2>
+      <span class="en">Framework Topics</span>
+      <span class="de">Framework-Themen</span>
+      <span class="es">Temas sobre el framework</span>
+      <span class="fr">Thèmes relatifs au framework</span>
+      <span class="it">Argomenti relativi al framework</span>
+      <span class="ja">フレームワーク トピック</span>
+      <span class="zh-CN">框架主题</span>
+      <span class="zh-TW">架構主題</span>
+    </h2>
+    <ul>
+      <li><a href="<?cs var:toroot ?>guide/topics/fundamentals.html">
+            <span class="en">Application Fundamentals</span>
+            <span class="de" style="display:none">Anwendungsgrundlagen</span>
+            <span class="es" style="display:none">Fundamentos de las aplicaciones</span>
+            <span class="fr" style="display:none">Principes de base des applications</span>
+            <span class="it" style="display:none">Concetti fondamentali sulle applicazioni</span>
+            <span class="ja" style="display:none">開発の基礎</span>
+            <span class="zh-CN" style="display:none">应用程序基础</span>
+            <span class="zh-TW" style="display:none">應用程式基本原理</span>
 
-<li><h2>Framework Topics</h2>
-    <ul>
-      <li><a href="<?cs var:toroot ?>guide/topics/fundamentals.html">Application Fundamentals</a></li>
+          </a></li>
     </ul>
     <ul>
       <li class="toggle-list">
-        <div><a href="<?cs var:toroot ?>guide/topics/ui/index.html">User Interface</a></div>
-          <ul>
-            <li><a href="<?cs var:toroot ?>guide/topics/ui/declaring-layout.html">Declaring Layout</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/ui/menus.html">Creating Menus</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/ui/dialogs.html">Creating Dialogs</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/ui/ui-events.html">Handling UI Events</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/ui/notifiers/index.html">Notifying the User</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/ui/themes.html">Applying Styles and Themes</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/ui/custom-components.html">Building Custom Components</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/ui/binding.html">Binding to Data with AdapterView</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/ui/layout-objects.html">Common Layout Objects</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/ui/how-android-draws.html">How Android Draws Views</a></li>
-          </ul>
+        <div><a href="<?cs var:toroot ?>guide/topics/ui/index.html">
+               <span class="en">User Interface</span>
+             </a></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/declaring-layout.html">
+               <span class="en">Declaring Layout</span> 
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/menus.html">
+               <span class="en">Creating Menus</span> 
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/dialogs.html">
+                <span class="en">Creating Dialogs</span> 
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/ui-events.html">
+                <span class="en">Handling UI Events</span> 
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/notifiers/index.html">
+                <span class="en">Notifying the User</span> 
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/themes.html">
+                <span class="en">Applying Styles and Themes</span> 
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/custom-components.html">
+                <span class="en">Building Custom Components</span> 
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/binding.html">
+                <span class="en">Binding to Data with AdapterView</span> 
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/layout-objects.html">
+                <span class="en">Common Layout Objects</span> 
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/how-android-draws.html">
+                <span class="en">How Android Draws Views</span> 
+              </a></li>
+        </ul>
       </li>
       <li class="toggle-list">
-        <div><a href="<?cs var:toroot ?>guide/topics/resources/index.html">Resources and Assests</a></div>
-          <ul>
-            <li><a href="<?cs var:toroot ?>guide/topics/resources/resources-i18n.html">Resources and I18n</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/resources/available-resources.html">Available Resource Types</a></li>
-          </ul>
+        <div><a href="<?cs var:toroot ?>guide/topics/resources/index.html">
+               <span class="en">Resources and Assests</span> 
+             </a></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>guide/topics/resources/resources-i18n.html">
+                <span class="en">Resources and I18n</span>
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/resources/available-resources.html">
+                <span class="en">Available Resource Types</span>
+              </a></li>
+        </ul>
       </li>
-      <li><a href="<?cs var:toroot ?>guide/topics/intents/intents-filters.html">Intents and Intent Filters</a></li>
-      <li><a href="<?cs var:toroot ?>guide/topics/data/data-storage.html">Data Storage</a></li>
-      <li><a href="<?cs var:toroot ?>guide/topics/providers/content-providers.html">Content Providers</a></li>
-      <li><a href="<?cs var:toroot ?>guide/topics/security/security.html">Security and Permissions</a></li>
-<!--  <li><a style="color:gray;">Processes and Threads</a></li> -->
-<!--  <li><a style="color:gray;">Interprocess Communication</a></li> -->
+      <li><a href="<?cs var:toroot ?>guide/topics/intents/intents-filters.html">
+            <span class="en">Intents and Intent Filters</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/topics/data/data-storage.html">
+            <span class="en">Data Storage</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/topics/providers/content-providers.html">
+            <span class="en">Content Providers</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/topics/security/security.html">
+            <span class="en">Security and Permissions</span>
+          </a></li>
+  <!--  <li><a style="color:gray;">Processes and Threads</a></li> -->
+  <!--  <li><a style="color:gray;">Interprocess Communication</a></li> -->
       <li class="toggle-list">
-        <div><a href="<?cs var:toroot ?>guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a></div>
-          <ul>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/action-element.html">&lt;action&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/application-element.html">&lt;application&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/category-element.html">&lt;category&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/data-element.html">&lt;data&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/instrumentation-element.html">&lt;instrumentation&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/service-element.html">&lt;service&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></li>
-          </ul>
+        <div><a href="<?cs var:toroot ?>guide/topics/manifest/manifest-intro.html">
+               <span class="en">The AndroidManifest.xml File</span>
+             </a></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/action-element.html">&lt;action&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/application-element.html">&lt;application&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/category-element.html">&lt;category&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/data-element.html">&lt;data&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/instrumentation-element.html">&lt;instrumentation&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/service-element.html">&lt;service&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></li>
+        </ul>
       </li>
     </ul>
     <ul>
       <li class="toggle-list">
-        <div><a href="<?cs var:toroot ?>guide/topics/graphics/index.html">Graphics</a></div>
-          <ul>
-            <li><a href="<?cs var:toroot ?>guide/topics/graphics/2d-graphics.html">2D Graphics</a></li>
-            <li><a href="<?cs var:toroot ?>guide/topics/graphics/opengl.html">3D with OpenGL</a></li>
-          </ul>
+        <div><a href="<?cs var:toroot ?>guide/topics/graphics/index.html">
+               <span class="en">Graphics</span>
+             </a></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>guide/topics/graphics/2d-graphics.html">
+                <span class="en">2D Graphics</span>
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/graphics/opengl.html">
+                <span class="en">3D with OpenGL</span>
+              </a></li>
+        </ul>
       </li>
-      <li><a href="<?cs var:toroot ?>guide/topics/media/index.html">Audio and Video</a></li>
-<!--       <li class="toggle-list">
+      <li><a href="<?cs var:toroot ?>guide/topics/media/index.html">
+            <span class="en">Audio and Video</span>
+          </a></li>
+  <!--<li class="toggle-list">
         <div><a style="color:gray;">Sensors</a></div>
           <ul>
             <li><a style="color:gray;">Camera</a></li>
@@ -86,115 +177,256 @@
             <li><a style="color:gray;">Accelerometer</a></li>
           </ul>
       </li> -->
-      <li><a href="<?cs var:toroot ?>guide/topics/location/index.html">Location and Maps</a></li>
-<!--    <li class="toggle-list">
+      <li><a href="<?cs var:toroot ?>guide/topics/location/index.html">
+            <span class="en">Location and Maps</span>
+          </a></li>
+  <!--<li class="toggle-list">
         <div><a style="color:gray;">Wireless Controls</a></div>
           <ul>
             <li><a style="color:gray;">Wi-Fi</a></li>
             <li><a style="color:gray;">Bluetooth</a></li>
           </ul>
       </li> -->
-<!--  <li><a style="color:gray;">Localization</a></li>  -->
-      <li><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html">App Widgets</a></li>
+  <!--<li><a style="color:gray;">Localization</a></li>  -->
+      <li><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html">
+            <span class="en">App Widgets</span>
+          </a></li>
     </ul>
-</li>
-
-<li><h2>Developing</h2>
+  </li>
+  
+  <li>
+    <h2><span class="en">Developing</span>
+               <span class="de">Entwicklung</span>
+               <span class="es">Desarrollo</span>
+               <span class="fr">Développement</span>
+               <span class="it">Sviluppo</span>
+               <span class="ja">開発</span>
+               <span class="zh-CN">开发</span>
+               <span class="zh-TW">開發</span>
+    </h2>
     <ul>
-      <!--       <li><a style="color:gray;">Developing for Android</a></li>
+  <!--<li><a href="">Developing for Android</a></li>
       signing, upgrading, selecting a package name, select device profile, touch, trackball, dpad available, etc. -->
-      <li><a href="<?cs var:toroot ?>guide/developing/eclipse-adt.html">In Eclipse, with ADT</a></li>
-      <li><a href="<?cs var:toroot ?>guide/developing/other-ide.html">In Other IDEs</a></li>
-      <li><a href="<?cs var:toroot ?>guide/developing/device.html">On a Device</a></li>
-      <li><a href="<?cs var:toroot ?>guide/developing/debug-tasks.html">Debugging Tasks</a></li>
+      <li><a href="<?cs var:toroot ?>guide/developing/eclipse-adt.html">
+            <span class="en">In Eclipse, with ADT</span> 
+            <span class="de" style="display:none">In Eclipse, mit ADT</span>
+            <span class="es" style="display:none">En Eclipse, con ADT</span>
+            <span class="fr" style="display:none">Sous Eclipse, à l'aide du plugin ADT</span>
+            <span class="it" style="display:none">In Eclipse, con ADT</span>
+            <span class="ja" style="display:none">Eclipse 内で ADT を使用</span>
+            <span class="zh-CN" style="display:none">利用 ADT 在 Eclipse 中开发</span>
+            <span class="zh-TW" style="display:none">在加裝 ADT 工具的 Eclipse 環境中</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/developing/other-ide.html">
+            <span class="en">In Other IDEs</span>
+            <span class="de" style="display:none">In anderen IDEs</span>
+            <span class="es" style="display:none">En otros entornos</span>
+            <span class="fr" style="display:none">Sous d'autres environnements</span>
+            <span class="it" style="display:none">In altri IDE</span>
+            <span class="ja" style="display:none">その他の統合開発環境</span>
+            <span class="zh-CN" style="display:none">在其他 IDE 中开发</span>
+            <span class="zh-TW" style="display:none">在其他開發環境中</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/developing/device.html">
+            <span class="en">On a Device</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/developing/debug-tasks.html">
+            <span class="en">Debugging Tasks</span>
+          </a></li>
       <li class="toggle-list">
-        <div><a href="<?cs var:toroot ?>guide/developing/tools/index.html">Tools</a></div>
-          <ul>
-			<li><a href="<?cs var:toroot ?>guide/developing/tools/aapt.html">aapt</a></li>
-			<li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html">adb</a></li>
-			<li><a href="<?cs var:toroot ?>guide/developing/tools/othertools.html#android">android</a></li>
-<!--			<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/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>
-			<li><a href="<?cs var:toroot ?>guide/developing/tools/emulator.html">Emulator</a></li>
-			<li><a href="<?cs var:toroot ?>guide/developing/tools/hierarchy-viewer.html">Hierarchy Viewer</a></li>
-			<li><a href="<?cs var:toroot ?>guide/developing/tools/othertools.html#mksdcard">mksdcard</a></li>
-			<li><a href="<?cs var:toroot ?>guide/developing/tools/monkey.html">Monkey</a></li>
-			<li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html#sqlite">sqlite3</a></li>
-			<li><a href="<?cs var:toroot ?>guide/developing/tools/traceview.html" >Traceview</a></li>
-		  </ul></li>
-<!--      <li><a href="<?cs var:toroot ?>guide/developing/instrumentation/index.html">Instrumentation</a></li>
+        <div><a href="<?cs var:toroot ?>guide/developing/tools/index.html">
+            <span class="en">Tools</span>
+          </a></div>
+        <ul>
+      		<li><a href="<?cs var:toroot ?>guide/developing/tools/aapt.html">aapt</a></li>
+      		<li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html">adb</a></li>
+      		<li><a href="<?cs var:toroot ?>guide/developing/tools/othertools.html#android">android</a></li>
+      <!--<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/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>
+      		<li><a href="<?cs var:toroot ?>guide/developing/tools/emulator.html">Emulator</a></li>
+      		<li><a href="<?cs var:toroot ?>guide/developing/tools/hierarchy-viewer.html">Hierarchy Viewer</a></li>
+      		<li><a href="<?cs var:toroot ?>guide/developing/tools/othertools.html#mksdcard">mksdcard</a></li>
+      		<li><a href="<?cs var:toroot ?>guide/developing/tools/monkey.html">Monkey</a></li>
+      		<li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html#sqlite">sqlite3</a></li>
+      		<li><a href="<?cs var:toroot ?>guide/developing/tools/traceview.html" >Traceview</a></li>
+    	  </ul>
+  	  </li>
+  <!--<li><a href="<?cs var:toroot ?>guide/developing/instrumentation/index.html">Instrumentation</a></li>
       <li><a style="color:gray;">JUnit</a></li> -->
-   </ul>
-
-</li>
-
-<li><h2>Publishing</h2>
-    <ul>
-      <li><a href="<?cs var:toroot ?>guide/publishing/app-signing.html">Signing Your Applications</a></li>
-      <li><a href="<?cs var:toroot ?>guide/publishing/versioning.html">Versioning Your Applications</a></li>
-      <li><a href="<?cs var:toroot ?>guide/publishing/preparing.html">Preparing to Publish</a></li>
-      <li><a href="<?cs var:toroot ?>guide/publishing/publishing.html">Publishing Your Applications</a></li>
     </ul>
-</li>
-
-<li><h2>Best Practices</h2>
+  </li>
+  
+  <li>
+    <h2><span class="en">Publishing</span>
+        <span class="de">Veröffentlichung</span>
+        <span class="es">Publicación</span>
+        <span class="fr">Publication</span>
+        <span class="it">Pubblicazione</span>
+        <span class="ja">公開</span>
+        <span class="zh-CN">发布</span>
+        <span class="zh-TW">發佈</span>
+    </h2>
+    <ul>
+      <li><a href="<?cs var:toroot ?>guide/publishing/app-signing.html">
+            <span class="en">Signing Your Applications</span>
+            <span class="de" style="display:none">Signieren Ihrer Anwendungen</span>
+            <span class="es" style="display:none">Firma de aplicaciones</span>
+            <span class="fr" style="display:none">Attribution de votre signature <br />à vos applications</span>
+            <span class="it" style="display:none">Firma delle applicazioni</span>
+            <span class="ja" style="display:none">アプリケーションへの署名</span>
+            <span class="zh-CN" style="display:none">应用程序签名</span>
+            <span class="zh-TW" style="display:none">簽署應用程式</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/publishing/versioning.html">
+            <span class="en">Versioning Your Applications</span>
+            <span class="de" style="display:none">Versionsverwaltung für Ihre <br />Anwendungen</span>
+            <span class="es" style="display:none">Versiones de las aplicaciones</span>
+            <span class="fr" style="display:none">Attribution d'une version à vos applications</span>
+            <span class="it" style="display:none">Controllo versioni delle applicazioni</span>
+            <span class="ja" style="display:none">アプリケーションのバージョニング</span>
+            <span class="zh-CN" style="display:none">应用程序版本控制</span>
+            <span class="zh-TW" style="display:none">應用程式版本設定</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/publishing/preparing.html">
+            <span class="en">Preparing to Publish</span>
+            <span class="de" style="display:none">Vorbereitung auf die Veröffentlichung</span>
+            <span class="es" style="display:none">Publicación de aplicaciones</span>
+            <span class="fr" style="display:none">Préparation à la publication</span>
+            <span class="it" style="display:none">Preparativi per la pubblicazione</span>
+            <span class="ja" style="display:none">公開の準備</span>
+            <span class="zh-CN" style="display:none">准备发布</span>
+            <span class="zh-TW" style="display:none">準備發佈</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/publishing/publishing.html">
+            <span class="en">Publishing Your Applications</span>
+          </a></li>
+    </ul>
+  </li>
+  
+  <li>
+    <h2><span class="en">Best Practices</span>
+               <span class="de">Bewährte Verfahren</span>
+               <span class="es">Prácticas recomendadas</span>
+               <span class="fr">Meilleures pratiques</span>
+               <span class="it">Best practice</span>
+               <span class="ja">ベスト プラクティス</span>
+               <span class="zh-CN">最佳实践</span>
+               <span class="zh-TW">最佳實務</span>
+    </h2>
     <ul>
       <li class="toggle-list">
-        <div><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/index.html">UI Guidelines</a></div>
-          <ul>
-            <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design.html">Icon Design</a></li>
-            <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/widget_design.html">App Widget Design</a></li>
-            <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/activity_task_design.html">Activity and Task Design</a></li>
-          </ul>
+        <div><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/index.html">
+               <span class="en">UI Guidelines</span>
+             </a></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design.html">
+                <span class="en">Icon Design</span>
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/widget_design.html">
+                <span class="en">App Widget Design</span>
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/activity_task_design.html">
+                <span class="en">Activity and Task Design</span>
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/menu_design.html">
+                <span class="en">Menu Design</span>
+              </a></li>
+        </ul>
       </li>
-      <li><a href="<?cs var:toroot ?>guide/practices/design/performance.html">Designing for Performance</a></li>
-      <li><a href="<?cs var:toroot ?>guide/practices/design/responsiveness.html">Designing for Responsiveness</a></li>
-      <li><a href="<?cs var:toroot ?>guide/practices/design/seamlessness.html">Designing for Seamlessness</a></li>
-<!--  <li><a style="color:gray;">User Interface Guidelines</a></li> -->
+      <li><a href="<?cs var:toroot ?>guide/practices/design/performance.html">
+            <span class="en">Designing for Performance</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/practices/design/responsiveness.html">
+            <span class="en">Designing for Responsiveness</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/practices/design/seamlessness.html">
+            <span class="en">Designing for Seamlessness</span>
+          </a></li>
     </ul>
-</li>
-
-<li><h2>Tutorials and Sample Code</h2>
+  </li>
+  
+  <li>
+    <h2><span class="en">Tutorials and Sample Code</span>
+               <span class="de">Lernprogramme und Beispielcode</span>
+               <span class="es">Tutoriales y código de ejemplo</span>
+               <span class="fr">Didacticiels et exemple de code</span>
+               <span class="it">Esercitazioni e codice di esempio</span>
+               <span class="ja">チュートリアルとサンプル コード</span>
+               <span class="zh-CN">辅导手册和示例代码</span>
+               <span class="zh-TW">教學課程與程式碼範例</span>
+    </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>guide/tutorials/hello-world.html">Hello World</a></li>
-      <li><a href="<?cs var:toroot ?>guide/tutorials/views/index.html">Hello Views</a></li>
-      <li><a href="<?cs var:toroot ?>guide/tutorials/notepad/index.html">Notepad Tutorial</a></li>
+      <li><a href="<?cs var:toroot ?>guide/tutorials/hello-world.html">
+            <span class="en">Hello World</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/tutorials/views/index.html">
+            <span class="en">Hello Views</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/tutorials/notepad/index.html">
+            <span class="en">Notepad Tutorial</span>
+          </a></li>
     </ul>
     <ul>
     <?cs if:android.whichdoc != "online" ?>
-      <li><a href="<?cs var:toroot ?>../samples">Sample Code &raquo;</a></li>
+      <li><a href="<?cs var:toroot ?>../samples">
+            <span class="en">Sample Code</span>
+          &raquo;</a></li>
     <?cs else ?>
       <li class="toggle-list">
-        <div><a href="<?cs var:toroot ?>guide/samples/index.html">Sample Code</a></div>
-	  <ul>
-            <li><a href="<?cs var:toroot ?>guide/samples/ApiDemos/index.html">API Demos</a></li>
-            <li><a href="<?cs var:toroot ?>guide/samples/LunarLander/index.html">Lunar Lander</a></li>
-            <li><a href="<?cs var:toroot ?>guide/samples/NotePad/index.html">NotePad</a></li>
-          </ul>
+        <div><a href="<?cs var:toroot ?>guide/samples/index.html">
+               <span class="en">Sample Code</span>
+             </a></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>guide/samples/ApiDemos/index.html">
+                <span class="en">API Demos</span>
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/samples/LunarLander/index.html">
+                <span class="en">Lunar Lander</span>
+              </a></li>
+          <li><a href="<?cs var:toroot ?>guide/samples/NotePad/index.html">
+                <span class="en">NotePad</span>
+              </a></li>
+        </ul>
       </li>
     <?cs /if ?>
     </ul>
-</li>
+  </li>
 
-
-
-<li><h2>Appendix</h2>
+  <li>
+    <h2><span class="en">Appendix</span>
+               <span class="de">Anhang</span>
+               <span class="es">Apéndice</span>
+               <span class="fr">Annexes</span>
+               <span class="it">Appendice</span>
+               <span class="ja">付録</span>
+               <span class="zh-CN">附录</span>
+               <span class="zh-TW">附錄</span>
+    </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>guide/appendix/media-formats.html">Supported Media Formats</a></li>
-      <li><a href="<?cs var:toroot ?>guide/appendix/g-app-intents.html">Intents List: Google Apps</a></li>
-      <li><a href="<?cs var:toroot ?>guide/appendix/glossary.html">Glossary</a></li>
-      <li><a href="<?cs var:toroot ?>guide/appendix/faq/index.html">FAQ</a></li>
+      <li><a href="<?cs var:toroot ?>guide/appendix/media-formats.html">
+            <span class="en">Supported Media Formats</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/appendix/g-app-intents.html">
+            <span class="en">Intents List: Google Apps</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/appendix/glossary.html">
+            <span class="en">Glossary</span>
+          </a></li>
+      <li><a href="<?cs var:toroot ?>guide/appendix/faq/index.html">
+            <span class="en">FAQ</span>
+          </a></li>
     </ul>
-</li>
+  </li>
 
 </ul>
 
 <script type="text/javascript">
 <!--
     buildToggleLists();
+    changeNavLang(getLangPref());
 //-->
 </script>
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design.jd b/docs/html/guide/practices/ui_guidelines/icon_design.jd
index 155684a..5f0a278 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design.jd
@@ -25,7 +25,7 @@
 
 <li style="margin-top:4px;"><a href="#dodonts">General guidelines</a></li>
 <li><a href="#templatespack">Using the Icon Templates Pack</a></li>
-<li><a href="#file">Icon appendix</a>
+<li><a href="#iconappendix">Icon appendix</a>
 	<ol>
 	<li><a href="#launcherapx">Launcher icons</a></li>
 	<li><a href="#menuapx">Menu icons</a></li>
@@ -989,25 +989,9 @@
 <table class="image-caption">
 <tr>
 
-
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_add.png" title="ic_menu_add" alt="Android asset" />
   <div class="caption">Add</div></td>
-	
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_archive.png" title="ic_menu_archive" alt="Android asset" />
-  <div class="caption">Archive</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_attachment.png" title="ic_menu_attachment" alt="Android asset" />
-  <div class="caption">Attach</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_back.png" title="ic_menu_back" alt="Android asset" />
-  <div class="caption">Back</div></td>
 
 
 <td class="image-caption-i image-list">
@@ -1024,9 +1008,6 @@
   <img src="{@docRoot}images/icon_design/ic_menu_close_clear_cancel.png" title="ic_menu_close_clear_cancel" alt="Android asset" />
   <div class="caption">Clear / Close / Cancel / Discard </div></td>
 
-</tr>
-<tr>
-
 
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_compass.png" title="ic_menu_compass" alt="Android asset" />
@@ -1036,40 +1017,24 @@
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_delete.png" title="ic_menu_delete" alt="Android asset" />
   <div class="caption">Delete</div></td>
-	
+
 
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_directions.png" title="ic_menu_directions" alt="Android asset" />
   <div class="caption">Directions</div></td>
-	
+
+</tr>
+<tr>
 
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_edit.png" title="ic_menu_edit" alt="Android asset" />
   <div class="caption">Edit</div></td>
 
 
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_favorite.png" title="ic_menu_favorite" alt="Android asset" />
-  <div class="caption">Favorite</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_forward.png" title="ic_menu_forward" alt="Android asset" />
-  <div class="caption">Forward</div></td>
-	
-
 <td class="image-caption-i image-list">	
   <img src="{@docRoot}images/icon_design/ic_menu_gallery.png" title="ic_menu_gallery" alt="Android asset" />
   <div class="caption">Gallery</div></td>
 
-</tr>
-<tr>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_goto.png" title="ic_menu_goto" alt="Android asset" />
-  <div class="caption">Go to</div></td>
-	
 
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_help.png" title="ic_menu_help" alt="Android asset" />
@@ -1077,16 +1042,6 @@
 
 
 <td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_recent_history.png" title="ic_menu_recent_history" alt="Android asset" />
-  <div class="caption">History</div></td>
-	
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_home.png" title="ic_menu_home" alt="Android asset" />
-  <div class="caption">Home</div></td>
-	
-
-<td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_info_details.png" title="ic_menu_info_details" alt="Android asset" />
   <div class="caption">Info / details</div></td>
 
@@ -1094,14 +1049,6 @@
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_mapmode.png" title="ic_menu_mapmode" alt="Android asset" />
   <div class="caption">Map mode</div></td>
-	
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_mark.png" title="ic_menu_mark" alt="Android asset" />
-  <div class="caption">Mark</div></td>
-
-</tr>
-<tr>
 
 
 <td class="image-caption-i image-list">
@@ -1113,11 +1060,8 @@
   <img src="{@docRoot}images/icon_design/ic_menu_more.png" title="ic_menu_more" alt="Android asset" />
   <div class="caption">More</div></td>
 
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_play_clip.png" title="ic_menu_play_clip" alt="Android asset" />
-  <div class="caption">Play</div></td>
-	
+</tr>
+<tr>
 
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_preferences.png" title="ic_menu_preferences" alt="Android asset" />
@@ -1125,11 +1069,6 @@
 
 
 <td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_refresh.png" title="ic_menu_refresh" alt="Android asset" />
-  <div class="caption">Refresh</div></td>
-	
-
-<td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_rotate.png" title="ic_menu_rotate" alt="Android asset" />
   <div class="caption">Rotate</div></td>
 
@@ -1138,9 +1077,6 @@
   <img src="{@docRoot}images/icon_design/ic_menu_save.png" title="ic_menu_save" alt="Android asset" />
   <div class="caption">Save</div></td>
 
-</tr>
-<tr>
-
 
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_send.png" title="ic_menu_send" alt="Android asset" />
@@ -1158,26 +1094,15 @@
 
 
 <td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_shuffle.png" title="ic_menu_shuffle" alt="Android asset" />
-  <div class="caption">Shuffle</div></td>
-	
-
-<td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_upload.png" title="ic_menu_upload" alt="Android asset" />
   <div class="caption">Upload</div></td>
-	
+
+</tr>
+<tr>
 
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/ic_menu_view.png" title="ic_menu_view" alt="Android asset" />
   <div class="caption">View</div></td>
-	
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/ic_menu_camera_video_view.png" title="ic_menu_camera_video_view" alt="Android asset" />
-  <div class="caption">Video</div></td>
-
-</tr>
-<tr>
 
 
 <td class="image-caption-i image-list">
@@ -1214,131 +1139,21 @@
 <tr>
 
 <td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_data_connected_3g.png" title="stat_sys_data_connected_3g" alt="Android asset" />
-  <div class="caption">3G</div></td>
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_signal_flightmode.png" title="stat_sys_signal_flightmode" alt="Android asset" />
-  <div class="caption">Airplane mode</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_notify_alarm.png" title="stat_notify_alarm" alt="Android asset" />
-  <div class="caption">Alarm</div></td>
-
-
-<td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/stat_sys_data_bluetooth.png" title="stat_sys_data_bluetooth" alt="Android asset" />
   <div class="caption">Bluetooth</div></td>
 
 
 <td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_data_bluetooth_connected.png" title="stat_sys_data_bluetooth_connected" alt="Android asset" />
-  <div class="caption">Bluetooth connected</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_notify_calendar.png" title="stat_notify_calendar" alt="Android asset" />
-  <div class="caption">Calendar</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_notify_disk_full.png" title="stat_notify_disk_full" alt="Android asset" />
-  <div class="caption">Disk full</div></td>
-
-</tr>
-<tr>
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_data_connected_e.png" title="stat_sys_data_connected_e" alt="Android asset" />
-  <div class="caption">EDGE</div></td>
-
-
-<td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/stat_notify_email_generic.png" title="stat_notify_email_generic" alt="Android asset" />
   <div class="caption">Email</div></td>
 
 
 <td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_notify_email.png" title="stat_notify_email" alt="Android asset" />
-  <div class="caption">Gmail</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_data_connected_g.png" title="stat_sys_data_connected_g" alt="Android asset" />
-  <div class="caption">GPRS</div></td>
-
-
-<td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/stat_notify_chat.png" title="stat_notify_chat" alt="Android asset" />
   <div class="caption">IM</div></td>
 
 
 <td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_install_complete.png" title="stat_sys_install_complete" alt="Android asset" />
-  <div class="caption">Installation complete</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_notify_musicplayer.png" title="stat_notify_musicplayer" alt="Android asset" />
-  <div class="caption">Music</div></td>
-
-</tr>
-<tr>
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_r_signal_4.png" title="stat_sys_r_signal_4" alt="Android asset" />
-  <div class="caption">Roaming</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_signal_4.png" title="stat_sys_signal_4" alt="Android asset" />
-  <div class="caption">Signal</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_signal_null.png" title="stat_sys_signal_null" alt="Android asset" />
-  <div class="caption">Signal unavailable</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_ringer_silent_old.png" title="stat_sys_ringer_silent_old" alt="Android asset" />
-  <div class="caption">Silent mode</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_notify_sms.png" title="stat_notify_sms" alt="Android asset" />
-  <div class="caption">SMS/MMS</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_speakerphone.png" title="stat_sys_speakerphone" alt="Android asset" />
-  <div class="caption">Speaker phone</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_notify_sync_anim0.png" title="stat_notify_sync_anim0" alt="Android asset" />
-  <div class="caption">Sync</div></td>
-
-</tr>
-<tr>
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_notify_sync_error.png" title="stat_notify_sync_error" alt="Android asset" />
-  <div class="caption">Sync error</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_data_usb.png" title="stat_sys_data_usb" alt="Android asset" />
-  <div class="caption">USB connected</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_ringer_vibrate.png" title="stat_sys_ringer_vibrate" alt="Android asset" />
-  <div class="caption">Vibrate</div></td>
-
-
-<td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/stat_notify_voicemail.png" title="stat_notify_voicemail" alt="Android asset" />
   <div class="caption">Voicemail</div></td>
 
@@ -1349,32 +1164,6 @@
 
 
 <td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_wifi_signal_4.png" title="stat_sys_wifi_signal_4" alt="Android asset" />
-  <div class="caption">WiFi</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_notify_wifi_in_range.png" title="stat_notify_wifi_in_range" alt="Android asset" />
-  <div class="caption">WiFi network available</div></td>
-
-</tr>
-<tr>
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_wifi_unavailable.png" title="stat_sys_wifi_unavailable" alt="Android asset" />
-  <div class="caption">WiFi unavailable</div></td>
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_battery_100.png" title="stat_sys_battery_100" alt="Android asset" />
-  <div class="caption">Battery 100%</div></td>
-
-
-<td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_battery_empty.png" title="stat_sys_battery_empty" alt="Android asset" />
-  <div class="caption">Battery empty</div></td>
-
-
-<td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/stat_sys_phone_call.png" title="stat_sys_phone_call" alt="Android asset" />
   <div class="caption">Call</div></td>
 
@@ -1383,6 +1172,8 @@
   <img src="{@docRoot}images/icon_design/stat_sys_phone_call_forward.png" title="stat_sys_phone_call_forward" alt="Android asset" />
   <div class="caption">Call forward</div></td>
 
+</tr>
+<tr>
 
 <td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/stat_sys_phone_call_on_hold.png" title="stat_sys_phone_call_on_hold" alt="Android asset" />
@@ -1390,13 +1181,6 @@
 
 
 <td class="image-caption-i image-list">
-  <img src="{@docRoot}images/icon_design/stat_sys_gps_on.png" title="stat_sys_gps_on" alt="Android asset" />
-  <div class="caption">GPS on</div></td>
-
-</tr>
-<tr>
-
-<td class="image-caption-i image-list">
   <img src="{@docRoot}images/icon_design/stat_notify_missed_call.png" title="stat_notify_missed_call" alt="Android asset" />
   <div class="caption">Missed call</div></td>
 
diff --git a/docs/html/guide/practices/ui_guidelines/index.jd b/docs/html/guide/practices/ui_guidelines/index.jd
index 0b9d275..2d14fa6 100644
--- a/docs/html/guide/practices/ui_guidelines/index.jd
+++ b/docs/html/guide/practices/ui_guidelines/index.jd
@@ -39,6 +39,14 @@
       multitasking, activity reuse, intents, the activity stack, and 
       tasks. It covers this all from a high-level design perspective.
 </dd>
+  <dt><a href="{@docRoot}guide/practices/ui_guidelines/menu_design.html">Menu Design Guidelines</a> </dt>
+  <dd>Android applications make use of Option menus and Context menus 
+      that enable users to perform operations and navigate to other parts
+      of your application or to other applications.  These guidelines describe
+      the difference between Options and Context menus, how to arrange
+      menu items, when to put commands on-screen, and other details about
+      menu design.
+</dd>
 </dl>
 
 
diff --git a/docs/html/guide/practices/ui_guidelines/menu_design.jd b/docs/html/guide/practices/ui_guidelines/menu_design.jd
new file mode 100644
index 0000000..518cea1
--- /dev/null
+++ b/docs/html/guide/practices/ui_guidelines/menu_design.jd
@@ -0,0 +1,507 @@
+page.title=Menu Design Guidelines
+@jd:body
+	
+<div id="qv-wrapper">
+<div id="qv">
+			
+<h2>Menu design quickview</h2>
+
+<ul>
+  <li>An Options menu is for any commands that are global to the current activity. </li>
+  <li>A Context menu is for any commands that apply to the current selection. </li>
+  <li>Place the most frequently used operations first. </li>
+  <li>Put only the most important commands fixed on the screen. </li>
+  <li>The commands on the Context menu that appears when you touch &amp; hold on an item should be duplicated on the activity you get to by a normal press on that item.
+</ul>
+
+
+<h2>In this document</h2>
+
+<ol>
+  <li><a href=#tour_of_the_menus>Tour of the Menus</a>
+	<ol>
+       <li style="padding-top: 4px;"><a href=#options_menu>Options Menu</a></li>
+       <li style="padding-top: 4px;"><a href=#context_menu>Context Menu</a></li>
+       <li style="padding-top: 4px;"><a href=#comparison_of_options_and_context_menus>Comparison of Options &amp; Context Menus</a></li>
+       <li style="padding-top: 4px;"><a href=#commands_fixed>Commands Fixed in an Activity Screen</a></li>
+	</ol>
+  </li>
+  <li><a href=#guidelines>Guidelines</a>
+	<ol>
+       <li style="padding-top: 4px;"><a href=#separate_commands>Separate specific from global commands</a></li>
+       <li style="padding-top: 4px;"><a href=#most_frequently_used>Place most frequently used first</a></li>
+       <li style="padding-top: 4px;"><a href=#dont_put_commands>Don't put commands <em>only</em> in a Context menu</li>
+       <li style="padding-top: 4px;"><a href=#first_in_context_menu>First command in Context menu should be most intuitive</li>
+       <li style="padding-top: 4px;"><a href=#selecting_content_item>Selecting an item should perform most intuitive operation</a></li>
+       <li style="padding-top: 4px;"><a href=#context_menu_should_identify>A Context menu should identify the selected item</li>
+       <li style="padding-top: 4px;"><a href=#most_important_commands>Put only most important commands fixed on the screen</a></li>
+       <li style="padding-top: 4px;"><a href=#short_names>Use short names in Options icon menu</a></li>
+       <li style="padding-top: 4px;"><a href=#a_dialog_should_not_have_an_options_menu>A dialog should not have Options menu</a></li>
+       <li style="padding-top: 4px;"><a href=#do_not_substitute_message>If no Options menu, don't display message</a></li>
+       <li style="padding-top: 4px;"><a href=#dim_hide_menu_items>Dim or hide menu items not available</a></li>
+	</ol>
+  </li>
+</ol>
+
+<h2>See also</h2>
+
+<ol>
+  <li><a href="http://android-developers.blogspot.com/2008/12/touch-mode.html">Touch mode</a></li>
+  <li><a href="{@docRoot}guide/practices/ui_guidelines/activity_task_design.html">Activity and Task Design</a></li>
+</ol>
+
+</div>
+</div>       
+
+<p>
+  A menu holds a set of commands (user actions) that are normally hidden, and
+  are accessible by a button, key, or gesture.  Menu commands provide a means
+  for performing operations and for navigating to other parts of your 
+  application or other applications.  Menus are useful for freeing screen space,
+  as an alternative to placing functionality and navigation, in buttons or other
+  user controls in the content area of your application. 
+</p>
+
+<p>
+  The Android system provides two types of menus you can use to provide
+  functionality or navigation. Between them, you should be able to organize
+  the functionality and navigation for your application.  Briefly:
+  <ul>
+    <li>The <em>Options menu</em> contains primary functionality that applies
+        globally to the current activity or starts a related activity. 
+        It is typically invoked by a user pressing a hard button, often labeled MENU.</li>
+    <li>The <em>Context menu</em> contains secondary functionality for the currently
+        selected item.  It is typically invoked by a user's touch &amp; hold
+        on an item.  Like on the Options menu, the operation can run either
+        in the current or another activity.</li>
+  </ul>
+</p>
+
+<p>
+  All but the simplest applications have menus.  The system automatically
+  lays the menus out and provides standard ways for users to access them.  
+  In this sense, they are familiar and dependable ways for users to access
+  functionality across all applications.  All menus are panels that "float"
+  on top of the activity screen and are smaller than full screen, so that the
+  application is still visible around its edges.  This is a visual reminder 
+  that a menu is an intermediary operation that disappears once it's used.
+</p>
+
+<p>
+  Let's start out with a quick tour of the menus.
+</p>
+
+<h2 id="tour_of_the_menus">Tour of the Menus</h2>
+
+<blockquote>
+  <b>NOTE</b> - Your menus and screens might not look like those shown in this document;
+  they may vary from one version of Android or device to another.
+</blockquote>
+
+<h3 id="options_menu">Options Menu</h3>
+
+<p>
+  The Options menu contains commands that apply globally across the current
+  activity, or can start another activity. They do not apply to a selected
+  item in the content (a <a href="#context_menu">Context menu</a> does that).  
+</p>
+
+<p>
+  On most devices, a user presses the MENU button to access the Options menu, 
+  as shown in the screenshot below.  To close the menu, the user presses 
+  MENU again, or presses the BACK button. 
+  In fact, to cancel out of any menu, press the BACK button.  (Pressing the MENU
+  button or touching outside the menu also works.)  Note that how to invoke this
+  menu may be different on different devices.
+</p>
+
+<p>
+  Each
+  <a href="{@docRoot}guide/practices/ui_guidelines/activity_task_design.html#activities">activity</a>
+  activity has its own set of operations and therefore its own Options menu.
+  An application with multiple activities would have a different Options menu 
+  for each activity. 
+</p>
+
+<p>
+  For example, in the message list view of an email program, the Options menu
+  might let you search the messages, compose a new message, refresh the list, 
+  or change the email settings.  The compose view of an email program would 
+  have a different Options menu, such as adding a CC field, attaching a file, 
+  or discarding the message.
+</p>
+
+<p id="options_icon_expanded_menus">
+  In order to handle a large number of menu items, the Options menu
+  progressively discloses them in two steps:
+</p>
+
+<ul>
+  <li>
+    <b>Options icon menu</b> - The first press of the MENU button displays a
+    non-scrollable grid of icons at the bottom of the screen.  (On the G1
+    phone, up to 6 buttons typically appear.)
+  </li>
+  <li>
+    <b>Options expanded menu</b> - If the activity has more menu items than will
+    fit on the icon menu, then the last icon is labeled "More" &mdash; selecting it
+    displays a list that can contain any number of menu items and will scroll 
+    as necessary.
+  </li>
+</ul>
+
+<img src={@docRoot}images/menu_design/MenuDiagram.png>
+
+<p>
+  On some versions of Android, the user can display keyboard shortcuts in the
+  icon menu by long pressing the MENU button &mdash; the text in the icon menu
+  alternates between the command names and their keyboard shortcuts (if any).
+</p>
+
+<h3 id="context_menu">Context Menu</h3>
+
+<p>
+  A Context menu is similar to a right-click context menu in a desktop
+  operating system.  It is normally a shortcut that duplicates commands
+  found elsewhere.
+</p>
+
+<p>
+  A user can touch &amp; hold on content on the screen to
+  access a Context menu (if one exists), as shown in the screenshot below. 
+  A Context menu is a list of menu items (commands) that can operate
+  on the selected content.  The command can either be part of the current
+  activity, or the system can pass the selected content along to 
+  an operation in another activity (by way of an 
+  <a href="{@docRoot}guide/practices/ui_guidelines/activity_task_design.html#intents">intent</a>).
+</p>
+
+<p>
+  For example, in an email message list, a user can touch &amp; hold on
+  an email message to open a Context menu containing commands to read,
+  archive, or delete the message. 
+</p>
+
+<p id="location">
+  A user can also touch &amp; hold a <em>location</em> on the screen to
+  access a Context menu.  An example is when the user does touch &amp; hold
+  on a blank spot on the Home screen, a Context menu appears; selecting
+  an item from that menu inserts an icon at that location.
+</p>
+
+<img src={@docRoot}images/menu_design/ContextMenuDiagram.png>
+
+<h4 id="context_menu_shortcut">Context Menu is a Shortcut</h4>
+
+<p>
+  In the above example, if the user performs touch &amp; hold on the contact
+  "Obi Wan Kenobi", a Context menu opens.  The commands provided in
+  this Context menu are the complete set of actions that can be performed
+  on this contact. 
+</p>
+
+<p>
+  A normal touch on an item in the content activates the most intuitive
+  command for that selection &mdash; in this case, "View contact".
+  We recommend that the most intuitive command also be listed as the
+  first item in the Context menu.  In this example, selecting the contact
+  "Obi Wan Kenobi" runs the same command "View contact" that is listed
+  at the top of the Context menu.
+</p>
+
+<p>
+  Also note, as shown in the following screenshot, the Context menu and the
+  next screen both hold the same complete set of commands that can be performed
+  on this contact.  The Context menu displays the commands in a list, 
+  while the "View contact" activity splits them into various items in the
+  Options menu, icon buttons and list items.
+</p>
+
+<p>
+  Because of this duplication, using the Context menu is considered a <em>shortcut</em>
+  for going to the next screen and performing the operation there.  Context menus
+  are less discoverable than either buttons fixed on-screen or the Options menu.
+  Many users never discover or use Context menus.  It is for this reason that, for
+  the most part, any command on a Context menu should also appear on the most
+  intuitive operation's screen.  As the next section explains, text operations,
+  such as "Select text" might appear only on a Context menu.  Also, rich
+  applications, such as browsers, which themselves can contain web applications,
+  may have commands on Context menus that are not available elsewhere.
+</p>
+
+<img src={@docRoot}images/menu_design/ContextMenuViewContactDiagram.png>
+
+<h4>Text Commands in Context Menu</h4>
+
+<p>
+  Text links and text fields in the content both have system-provided operations 
+  that are common across all applications: operations such as "Select all", "Select text",
+  "Copy all", and "Add to dictionary".  If the text field is editable, it also 
+  has  other operations, such as "Cut all" and "Input Method", and if text 
+  is also on the clipboard, it has "Paste".  The system automatically inserts
+  the appropriate menu items into the Context menu of text links and text
+  fields, as shown in the following screenshot.
+</p>
+
+<img src={@docRoot}images/menu_design/TextFieldContextMenuDiagram.png>
+
+
+<h3 id="comparison_of_options_and_context_menus">Comparison of Options and Context Menus</h3>
+
+<p>
+	An Options menu holds commands that are global to the activity while a
+	Context menu holds commands that apply only to an item in the content.
+    As shown in these diagrams, the user navigates to the menu, then
+    touches a menu item to perform an action or open a dialog.
+</p>
+
+<img src={@docRoot}images/menu_design/TaskFlowDiagram.png>
+
+<p>
+  For more technical information on menus, see
+  <a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>.
+</p>
+
+<h3 id="commands_fixed">Commands Fixed in an Activity Screen</h4>
+
+<p>
+  Commands can also be fixed directly on screen, typically in
+  text buttons, graphic buttons, or list items.  This placement is by far the most
+  discoverable location for commands &mdash; a user can immediately see the command
+  without having to first press a button.  This increased visibility needs to be
+  weighed against the space such user controls take up, or the sense that they
+  might clutter the visual design.
+</p>
+
+<h2 id="guidelines">Guidelines</h2>
+
+<p>
+  Selecting the right kind of menu to present, and using menus
+  consistently, are critical factors in good application design. The following
+  guidelines should assist user experience designers and application developers
+  toward this end.
+</p>
+
+<h3 id="separate_commands">Separate selection-specific commands from global commands</h3>
+
+<p>
+  Put any commands that are global to the current activity in the Options menu
+  or place them fixed in an activity screen; put commands that apply to the
+  current selection in the Context menu.  (In any case, the command
+  could either run as part of this activity or start another activity.)
+</p>
+
+<p>
+  You can determine in which menu to place a command by what it operates on:
+  If the command acts on selected content (or a particular
+  <a href="#location">location</a>) on the screen, put the command in the
+  Context menu for that content.  If the command acts on no specific content
+  or location, put it in the Options menu.  This separation of commands
+  is enforced by the system in the following way.  When you press the MENU
+  button to display the Options menu, the selected content becomes unselected,
+  and so cannot be operated on.  For an explanation
+  of why the content becomes unselected, see the article on
+  <a href="http://android-developers.blogspot.com/2008/12/touch-mode.html">Touch mode</a>.
+</p>
+
+<p>
+  An example of a selection-specific Context menu is when a user performs a
+  touch &amp; hold on a person's name in a list view of a contacts application.
+  The Context menu would typically contain commands "View contact", "Call contact",
+  and "Edit contact".  
+</p>
+
+<h3 id="most_frequently_used">Place the most frequently used operations first</h3>
+
+<p>
+  Because of limited screen height, some menus may be scrollable, so it's
+  important to place the most important commands so they can be viewed without
+  scrolling.  In the case of the Options menu, place the most frequently used
+  operation on its <a href="#options_icon_expanded_menus">icon menu</a>;
+  the user will have to select "More" to see the rest.
+  It's also useful to place similar commands in the same location &mdash;
+  for example, the Search icon might always be the first icon in the Options
+  menu across several activities that offer search.
+</p>
+
+<p>
+  In a Context menu, the most intuitive command should be first, followed
+  by commands in order of decreasing use, with the least used command at the bottom.
+</p>
+
+<h3 id="dont_put_commands">Don't put commands <em>only</em> in a Context menu</h3>
+<p>
+  If a user can fully access your application without using Context menus, 
+  then it's designed properly!  In general, if part of your application is inaccessible
+  without using Context menus, then you need to duplicate those commands elsewhere.
+</p>
+
+<p>
+  Before opening a Context menu, it has no visual representation that identifies
+  its presence (whereas the Options menu has the MENU button), and so is not
+  particularly discoverable. 
+  Therefore, in general, a Context menu should <em>duplicate</em> commands 
+  found in the corresponding activity screen.  For example, while it's useful to
+  let the user call a phone number from a Context menu invoked by touch
+  &amp; hold on a name in a list of contacts, that operation should <em>also</em>
+  be available by the user touching the phone number itself when viewing contact details.
+  See <a href="#context_menu_shortcut">shortcut</a> for an illustration of this example.
+</p>
+
+<h3 id="first_in_context_menu">The first command in a Context menu should be the selection's most intuitive command</h3>
+
+<p>
+  As described under <a href="#context_menu_shortcut">shortcut</a>,
+  touching on an item in the content should activate the same command as touching
+  the first item in the Context menu.  Both cases should be the most intuitive
+  operation for that item.  
+</p>
+
+<h3 id="selecting_content_item">Selecting an item in the content should perform the most intuitive operation</h3>
+
+<p>
+  In your application, when the user touches any actionable text (such as a link
+  or list item) or image (such as a photo icon), execute the operation most
+  likely to be desired by the user.
+</p>
+
+<p>
+  Some examples of primary operations:
+</p>
+
+<ul>
+    <li>Selecting an image executes "View image"</li>
+    <li>Selecting a media icon or filename executes "Play"</li>
+    <li>Selecting a URL link executes "Open link"</li>
+    <li>Selecting an address executes "Go to address" (in a maps application)</li>
+</ul>
+
+<p>
+  Note that selecting the same item in different contexts might invoke
+  different operations:
+</p>
+
+<ul>
+    <li>In a contact application, selecting a contact executes "View details"</li>
+    <li>In an IM application, selecting a contact executes "Start chat"</li>
+    <li>In an Email application, when adding a recipient to the "To" field
+        through the contact book, selecting a contact executes "Add to recipient
+        list"</li>
+</ul>
+
+
+<h3 id="context_menu_should_identify">A Context menu should identify the selected item</h3>
+
+<p>
+  When a user does touch &amp; hold on an item, the Context menu should 
+  contain the name of the selected item.  Therefore, 
+  when creating a Context menu, be sure to include a title and the name of the
+  selected item so that it's clear to the user what the context is.  
+  For example, if a user selects a contact "Joan of Arc", put that name in the
+  title of the Context menu (using
+  {@link android.view.ContextMenu#setHeaderTitle(java.lang.CharSequence) setHeaderTitle}). 
+  Likewise, a command to edit the contact should be called "Edit contact",
+  not just "Edit".
+</p>
+
+
+<h3 id="most_important_commands">Put only the most important commands fixed on the screen</h3>
+
+<p>
+  By putting commands in menus, you free up the screen to hold more content. 
+  On the other hand, fixing commands in the content area of an activity
+  makes them more prominent and easy to use.
+</p>
+
+<p>
+  Here are a number of important reasons to place commands fixed on the activity screen:
+</p>
+
+  <ul>
+    <li>
+      To give a command the highest prominence, ensuring the command is obvious and won't be overlooked.<br>
+      Example: A "Buy" button in a store application.
+    </li>
+    <li> 
+      When quick access to the command is important and going to the menu would be
+      tedious or slow.<br>
+      Example: Next/Previous buttons or Zoom In/Out buttons in an image viewing application.
+    </li>
+    <li>
+      When in the middle of an operation that needs to be completed.<br>
+      Example: Save/Discard buttons in an image crop activity.
+    </li>
+    <li>
+      Dialogs and wizards.<br>
+      Example: OK/Cancel buttons
+    </li>
+    <li>
+      For direct manipulation.<br>
+      Example: Dragging an icon in the Home screen to the trash
+    </li>
+  </ul>
+
+<h3 id="short_names">Use short names in the Options icon menu</h3>
+
+<p>
+  If a text label in the <a href="#options_icon_expanded_menus">Options icon menu</a>
+  is too long, the system truncates it in the middle.  Thus, "Create Notification"
+  is truncated to something like "Create…ication". You have no control over
+  this truncation, so the best bet is to keep the text short.  In some versions of Android,
+  when the icon is highlighted by a navigation key (such as a trackball), the
+  entire descriptive text may be shown as a marquee, where the words are
+  readable as they scroll by.  <!--For more information, see the Text Guidelines
+  [update link].-->
+</p>
+
+<h3 id="a_dialog_should_not_have_an_options_menu">A dialog should not have an Options menu</h3>
+
+<p>
+  When a dialog is displayed, pressing the MENU button should do nothing.  This also holds true
+  for activities that look like dialogs.  A dialog box is recognizable by being
+  smaller than full-screen, having zero to three buttons, is non-scrollable, and 
+  possibly a list of selectable items that can include checkboxes or radio buttons.
+  <!--For examples of dialogs, see Text Guidelines.-->
+</p>
+
+<p>
+  The rationale behind not having a menu is that when a dialog is displayed, the user is in
+  the middle of a procedure and should not be allowed to start a new global task
+  (which is what the Option menu provides).
+</p>
+
+<h3 id="do_not_substitute_message">If an activity has no Options menu, do not display a message</h3>
+
+<p>
+  When the user presses the MENU button, if there is no Options menu, the system
+  currently does nothing.  We recommend you do not perform any action (such as
+  displaying a message).  It's a better user experience for this behavior to be
+  consistent across applications.
+</p>
+
+
+
+<h3 id="dim_hide_menu_items">Dim or hide menu items that are not available in the current context</h3>
+
+<p>
+  Sometimes a menu item's action cannot be performed &mdash; for example,
+  the "Forward" button in a browser cannot work until after the "Back" 
+  button has been pressed. We recommend:
+</p>
+
+<ul>
+  <li> 	
+    <b>In Options menu</b> - disable the menu item, which dims the text and icon,
+    turning it gray.  This applies to menu items in both the icon menu and the
+    "More" menu.  It would be disorienting for the icon menu to change from 6
+    items to 5 items, and we treat the "More" menu the same way.
+  </li>
+  <li>
+    <b>In Context menu</b> - hide the menu item.  This makes the menu shorter so the
+    user sees only available choices (which also reduces any scrolling).
+  </li>
+</ul>
+
+</body>
+</html>
+
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index 01a9648..fc0061d 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -150,14 +150,26 @@
       <code>(number of cells * 74) - 2</code><br/>
     Following this formula, you should use 72 dp for a height of one cell, 294 dp and for a width of four cells.</p>
   </li>
-  <li>The <code>updatePerdiodMillis</code> attribute defines how often the App Widget framework should
+  <li>The <code>updatePeriodMillis</code> attribute defines how often the App Widget framework should
     request an update from the {@link android.appwidget.AppWidgetProvider} by calling the
     {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[])
     onUpdate()} method. The actual update is not guaranteed to occur exactly on time with this value
     and we suggest updating as infrequently as possible&mdash;perhaps no more than once an hour to 
     conserve the battery. You might also allow the user to adjust the frequency in a 
     configuration&mdash;some people might want a stock ticker to update every 15 minutes, or maybe 
-    only four times a day.</li>
+    only four times a day. 
+    	<p class="note"><strong>Note:</strong> If the device is asleep when it is time for an update 
+    	(as defined by <code>updatePeriodMillis</code>), then the device will wake up in order 
+    	to perform the update. If you don't update more than once per hour, this probably won't 
+    	cause significant problems for the battery life. If, however, you need to update more 
+    	frequently and/or you do not need to update while the device is asleep, then you can instead 
+    	perform updates based on an alarm that will not wake the device. To do so, set an alarm with 
+    	an Intent that your AppWidgetProvider receives, using the	{@link android.app.AlarmManager}. 
+    	Set the alarm type to either {@link android.app.AlarmManager#ELAPSED_REALTIME} or 
+    	{@link android.app.AlarmManager#RTC}, which will only
+    	deliver the alarm when the device is awake. Then set <code>updatePeriodMillis</code> to 
+    	zero (<code>"0"</code>).</p>
+  </li>
   <li>The <code>initialLayout</code> attribute points to the layout resource that defines the
     App Widget layout.</li>
   <li>The <code>configure</code> attribute defines the {@link android.app.Activity} to launch when
diff --git a/docs/html/guide/topics/resources/resources-i18n.jd b/docs/html/guide/topics/resources/resources-i18n.jd
index c26cb63..85b89d1 100755
--- a/docs/html/guide/topics/resources/resources-i18n.jd
+++ b/docs/html/guide/topics/resources/resources-i18n.jd
@@ -465,37 +465,37 @@
     </tr>
     <tr>
       <td>MCC and MNC</td>
-      <td>The mobile country code optionally followed by mobile network code
+      <td><p>The mobile country code optionally followed by mobile network code
       from the SIM in the device. For example
       <code>mcc310</code> (U.S. on any carrier);
       <code>mcc310-mnc004</code> (U.S., Verizon brand);
       <code>mcc208-mnc00</code> (France, Orange brand);
       <code>mcc234-mnc00</code> (U.K., BT brand).
-        <p>
+        </p><p>
         If the device uses a radio connection  (GSM phone), the MCC will come
         from the SIM, and the MNC will come from the  network to which the
         device is attached. You might sometimes use the MCC alone, for example
         to include country-specific legal resources in your application. If
         your application specifies resources for a MCC/MNC  combination, those
-        resources can only be used if both the MCC and the MNC match. </td>
+        resources can only be used if both the MCC and the MNC match. </p></td>
     </tr>
     <tr>
         <td>Language and region</td>
-        <td>The two letter <a href="http://www.loc.gov/standards/iso639-2/php/code_list.php">ISO
+        <td><p>The two letter <a href="http://www.loc.gov/standards/iso639-2/php/code_list.php">ISO
                 639-1</a> language code optionally followed by a two letter
                 <a href="http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">ISO
                 3166-1-alpha-2</a> region code (preceded by lowercase &quot;r&quot;). For example 
                 <code>fr</code>, <code>en-rUS</code>, <code>fr-rFR</code>, <code>es-rES</code>.
-                <p>
+          </p><p>
           The codes are <em>not</em> case-sensitive; the r prefix is used to
           distinguish the region portion.
           You cannot specify a region alone, but you can specify a language alone,
-          for example <code>en</code>, <code>fr</code>, <code>es</code>. </td>
+          for example <code>en</code>, <code>fr</code>, <code>es</code>.</p> </td>
     </tr>
     <tr>
         <td>Screen dimensions</td>
-        <td><code>small</code>, <code>normal</code>, <code>large</code>
-        <p>
+        <td><p><code>small</code>, <code>normal</code>, <code>large</code>
+        </p><p>
         Specify that the resource is for a particular class of screen.
         The meanings of these are:</p>
         <ul>
@@ -517,27 +517,27 @@
     </tr>
     <tr>
         <td>Wider/taller screens</td>
-        <td><code>long</code>, <code>notlong</code>
-        <p>
+        <td><p><code>long</code>, <code>notlong</code>
+        </p><p>
         Specify that the resource is for a taller/wider than traditional
         screen.  This is based purely on the aspect ration of the screen:
         QVGA, HVGA, and VGA are notlong; WQVGA, WVGA, FWVGA are long.  Note
         that long may mean either wide or tall, depending on the current
-        orientation.
+        orientation.</p>
         </td>
     </tr>
     <tr>
         <td>Screen orientation</td>
-        <td><code>port</code>, <code>land</code>, <code>square</code>
-        <p>
+        <td><p><code>port</code>, <code>land</code>, <code>square</code>
+        </p><p>
         Specifies that the resource is for a screen that is tall (port)
-        or wide (land); square is not currently used.
+        or wide (land); square is not currently used.</p>
         </td>
     </tr>
     <tr>
         <td>Screen pixel density</td>
-        <td><code>ldpi</code>, <code>mdpi</code>, <code>hdpi</code>, <code>nodpi</code>
-        <p>
+        <td><p><code>ldpi</code>, <code>mdpi</code>, <code>hdpi</code>, <code>nodpi</code>
+        </p><p>
          Specifies the screen density the resource is defined for.  The medium
          density of traditional HVGA screens (mdpi) is defined to be approximately
          160dpi; low density (ldpi) is 120, and high density (hdpi) is 240.  There
@@ -545,7 +545,7 @@
          in ldpi would be 12x12 is mdpi and 16x16 in hdpi.  The special
          <code>nodpi</code> density can be used with bitmap resources to prevent
          them from being scaled at load time to match the device density.
-        <p>
+        </p><p>
          When Android selects which resource files to use,
          it handles screen density  differently than the other qualifiers.
          In step 1 of <a href="#best-match">How Android finds the best
@@ -553,10 +553,11 @@
          be a match. In step 4, if the qualifier being considered is screen
          density, Android will select the best final match at that point,
          without any need to move on to step 5.
-         <p>
+         </p><p>
          You can also specify explicit densities like <code>92dpi</code>
          or <code>108dpi</code>, but these are not fully supported by the
          system so should not be used.
+         </p>
          </td>
     </tr>
     <tr>
@@ -565,9 +566,9 @@
     </tr>
     <tr>
         <td>Whether the keyboard is available to the user</td>
-        <td><code>keysexposed</code>, <code>keyshidden</code>, <code>keyssoft</code>
-        <p>
-          If your application has specific resources that should only be used with a soft keyboard, use the <code>keyssoft</code> value. If no <code>keyssoft</code> resources are available (only <code>keysexposed</code> and <code>keyshidden</code>) and the device  shows a soft keyboard,  the system will use <code>keysexposed</code> resources. </td>
+        <td><p><code>keysexposed</code>, <code>keyshidden</code>, <code>keyssoft</code>
+        </p><p>
+          If your application has specific resources that should only be used with a soft keyboard, use the <code>keyssoft</code> value. If no <code>keyssoft</code> resources are available (only <code>keysexposed</code> and <code>keyshidden</code>) and the device  shows a soft keyboard,  the system will use <code>keysexposed</code> resources.</p> </td>
     </tr>
     <tr>
         <td>Primary text input method</td>
diff --git a/docs/html/images/menu_design/ContextMenuDiagram.png b/docs/html/images/menu_design/ContextMenuDiagram.png
new file mode 100644
index 0000000..06678c7
--- /dev/null
+++ b/docs/html/images/menu_design/ContextMenuDiagram.png
Binary files differ
diff --git a/docs/html/images/menu_design/ContextMenuViewContactDiagram.png b/docs/html/images/menu_design/ContextMenuViewContactDiagram.png
new file mode 100644
index 0000000..dcee981
--- /dev/null
+++ b/docs/html/images/menu_design/ContextMenuViewContactDiagram.png
Binary files differ
diff --git a/docs/html/images/menu_design/MenuDiagram.png b/docs/html/images/menu_design/MenuDiagram.png
new file mode 100644
index 0000000..543328a
--- /dev/null
+++ b/docs/html/images/menu_design/MenuDiagram.png
Binary files differ
diff --git a/docs/html/images/menu_design/TaskFlowDiagram.png b/docs/html/images/menu_design/TaskFlowDiagram.png
new file mode 100644
index 0000000..0157132
--- /dev/null
+++ b/docs/html/images/menu_design/TaskFlowDiagram.png
Binary files differ
diff --git a/docs/html/images/menu_design/TextFieldContextMenuDiagram.png b/docs/html/images/menu_design/TextFieldContextMenuDiagram.png
new file mode 100644
index 0000000..b23a7da
--- /dev/null
+++ b/docs/html/images/menu_design/TextFieldContextMenuDiagram.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 07d0abe..c39e9a8 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -11,19 +11,19 @@
                             </div><!-- end homeTitle -->
                             <div id="announcement-block">
                             <!-- total max width is 520px -->
-                                <img src="/assets/images/home/IO-logo.png" alt="Google I/O Developer Conference 2009" width="242px" />
-                                <div id="announcement" style="width:270px">
-                                  <p>Google I/O is a two-day developer event that will take place May 27-28 at Moscone Center, San Francisco. The agenda includes a number of great sessions on Android topics by team engineers and other developers.</p>
-                                  <p><a href="http://code.google.com/events/io/">Learn more &raquo;</a></p>
+                                <img src="/assets/images/home/android_adc.png" alt="Android Developer Challenge 2" width="232px" />
+                                <div id="announcement" style="width:275px">
+                                  <p>The second Android Developer Challenge has begun! In this contest,
+                                  real-world users will help review and score applications and the overall winner will 
+                                  take away $250,000. The deadline for submitting an application to the contest is August 31, 2009.</p>
+                                  <p><a href="http://code.google.com/android/adc/">Learn more about ADC 2 &raquo;</a></p>
                                 </div> <!-- end annoucement -->
                             </div> <!-- end annoucement-block -->  
                         </div><!-- end topAnnouncement -->
-                        <div id="carousel">
-                            <div id="carouselMain">
-                                <div id="bulletinImg"></div>
-                                <div id="bulletinDesc"></div>
-                            </div>
+                        <div id="carouselMain" style="height:192px"> <!-- this height can be adjusted based on the content height -->
+                        </div>
                             <div class="clearer"></div>
+                        <div id="carouselWheel">
                             <div class="app-list-container" align="center"> 
                                 <a href="javascript:{}" id="arrow-left" onclick="" class="arrow-left-off"></a>
                                 <div id="list-clip">
@@ -31,10 +31,10 @@
                                       <!-- populated by buildCarousel() -->
                                     </div>
                                 </div><!-- end list-clip -->
-                                <a href="javascript:page_right()" id="arrow-right" onclick="" class="arrow-right-on"></a>
+                                <a href="javascript:{ page_right(); }" id="arrow-right" onclick="" class="arrow-right-on"></a>
                                 <div class="clearer"></div>
                             </div><!-- end app-list container -->
-                        </div><!-- end carousel -->
+                        </div><!-- end carouselWheel -->
                     </div><!-- end homeMiddle -->
 
                     <div style="clear:both">&nbsp;</div>
@@ -79,8 +79,8 @@
                                       <td class="imageCell"><a href="http://www.youtube.com/user/androiddevelopers"><img src="{@docRoot}assets/images/video-droid.png" style="padding:0" /></a></td>
                                       <td>
                                               <h2 class="green">Watch</h2>
-                                              <object width="150" height="140"><param name="movie" value="http://www.youtube.com/v/x1ZZ-R3p_w8&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/x1ZZ-R3p_w8&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="150" height="140"></embed></object>
-                                              <p style="margin-top:1em"><a href="http://www.youtube.com/user/androiddevelopers">More Android videos &raquo;</a></p>
+                                              <object width="150" height="140"><param name="movie" value="http://www.youtube.com/v/GARMe7Km_gk&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/GARMe7Km_gk&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="150" height="140"></embed></object>
+                                              <p style="margin-top:1em"><a href="{@docRoot}videos/index.html">More Android videos &raquo;</a></p>
                                       </td>
                               </tr>
 
@@ -120,10 +120,19 @@
     'sdk': {
       'layout':"imgLeft",
       'icon':"sdk-small.png",
-      'name':"SDK 1.5 r2",
+      'name':"SDK 1.5 r3",
       'img':"sdk-large.png",
       'title':"Android 1.5 SDK",
-      'desc': "<p>Android 1.5 SDK is now available. It includes new APIs for Android 1.5, updated developer tools, multiple platform versions, and a Google APIs add-on.</p><p><a href='{@docRoot}sdk/1.5_r2/index.html'>Download Android 1.5 SDK</a></p>"
+      'desc': "<p>Android 1.5 SDK is now available. It includes new APIs for Android 1.5, updated developer tools, multiple platform versions, and a Google APIs add-on.</p><p><a href='{@docRoot}sdk/1.5_r3/index.html'>Download Android 1.5 SDK &raquo;</a></p>"
+    },
+    
+    'io': {
+      'layout':"imgLeft",
+      'icon':"io-small.png",
+      'name':"Google I/O",
+      'img':"io-large.png",
+      'title':"Google I/O Developer Conference",
+      'desc': "<p>The Google I/O developer conference took place May 27-28 in San Francisco. If you missed the conference, you can experience the Android sessions by viewing YouTube videos.</p><p><a href='{@docRoot}videos/index.html'>See the sessions from Google I/O &raquo;</a></p>"
     },
 
     'mapskey': {
@@ -135,15 +144,6 @@
       'desc':"<p>If you're writing an Android application that uses Google Maps (with MapView), you must register your application to obtain a Maps API Key. Without the key, your maps application will not work on Android devices. Obtaining a key requires just a couple of steps.</p><p><a href='http://code.google.com/android/add-ons/google-apis/maps-overview.html'>Learn more &raquo;</a></p>"
     },
 
-    'market': {
-      'layout':"imgTop",
-      'icon':"market-small.png",
-      'name':"Android Market",
-      'img':"market-large.png",
-      'title':"",
-      'desc': "<p>Android Market helps you get your applications into the hands of users. The beta version of Market is now open and you can begin sharing your applications with users of the first Android-powered phone, the T-Mobile G1.</p><p><a href='http://market.android.com/publish/'>Publish your Android app on Market &raquo;</a></p>"
-    },
-
     'devphone': {
       'layout':"imgLeft",
       'icon':"devphone-small.png",
diff --git a/docs/html/intl/ja/community/index.jd b/docs/html/intl/ja/community/index.jd
new file mode 100644
index 0000000..e0a645b
--- /dev/null
+++ b/docs/html/intl/ja/community/index.jd
@@ -0,0 +1,108 @@
+community=true
+page.title=コミュニティ
+@jd:body
+
+	<div id="mainBodyFluid">
+			<h1>コミュニティ</h1>
+			<p>Android デベロッパー コミュニティへようこそ。コミュニティでのディスカッションにぜひ参加してください。投稿する前に、コミュニティ ガイドラインが記載されている<a href="http://source.android.com/discuss/android-discussion-groups-charter">グループの趣意</a>をお読みください。</p>
+
+<p class="note"><strong>注:</strong> Android ソース コード(アプリケーション開発ではなく)に関するディスカッションは、<a href="http://source.android.com/discuss">オープンソース プロジェクトのメーリング リスト</a>(英語)を参照してください。</p>
+
+<p style="margin-bottom:.5em"><strong>目次</strong></p>
+<ol class="toc">
+  <li><a href="#BeforeYouPost">質問を投稿する前に</a></li>
+  <li><a href="#ApplicationDeveloperLists">アプリケーション デベロッパー メーリング リスト</a></li>
+  <li><a href="#UsingEmail">メーリング リストにメールを使用</a></li>
+  <li><a href="#UsingIRC">IRC の使用</a></li>
+</ol>
+
+<h2 id="BeforeYouPost">質問を投稿する前に</h2>
+<p>投稿を作成する前に、下記をお試しください:</p>
+
+<ol>
+<li><a href="{@docRoot}guide/appendix/faq/index.html">よくある質問を参照します</a>。Android アプリケーションの開発について非常に一般的な質問が、この一覧に記載されており、頻繁に更新されています。</li>
+<li><strong>Android のメイン サイトの検索バー(このページの上部にあるのと同じもの)に、調べたいキーワードを入力してください</strong>。この検索は、サイト、ドキュメント、ブログに含まれるすべてのコンテンツの他に、すべてのグループで以前行われたすべてのディスカッションを網羅しています。誰か他の人が、以前にも同じ問題に遭遇した可能性は大いにあります。</li>
+<li><b>メーリング リストのアーカイブを検索</b>して、同じ質問に関するディスカッションが既に存在しないか調べてください。
+  </li>
+</ol>
+
+<p>質問への答えが見つからない場合、コミュニティで質問することをおすすめします。投稿する際は、次の手順に従ってください。
+<ol>
+<li>コミュニティ ガイドラインが記載されている<b><a href="http://sites.google.com/a/android.com/opensource/discuss/android-discussion-groups-charter">Android メーリングリストの趣意</a></b>をお読みください。 
+</li>
+<li><b>質問に最適なメーリング リストを選択してください</b>。後述するように、デベロッパー向けのメーリング リストは何種類かに分かれています。</li>
+<li>
+    <b>質問の内容を明確に</b>。明確な質問は、回答者と、将来情報を探そうとする人の双方にとって有益です。</li>
+<li><b>投稿は詳しく書いてください</b>。回答者の人たちが問題を理解するのに役立ちます。コードやログのスニペット、スクリーンショットへのリンクを含めることも有用です。質問をわかりやすく表現するための詳しいガイドラインは、<a href="http://www.catb.org/%7Eesr/faqs/smart-questions.html">賢い質問のしかた</a>(英語)をご覧ください。
+  </li>
+</ol>
+
+
+<h3 id="ApplicationDeveloperLists">アプリケーション デベロッパー メーリング リスト</h3>
+<ul>
+<li><b>Android 初心者向け</b> - Android アプリケーションの開発初心者向けです。Android SDK と基本的な Android API の利用方法について学習したい場合は、このメーリング リストから始めてください。このメーリング リストには、SDK を利用するデベロッパーの初歩的なディスカッションの場所です。Android プラットフォームで初めてアプリケーションを作成して実行する際は、非常に有益な情報を得ることができるでしょう。開発環境のインストール方法についての質問を投稿したり、Android 開発の初歩(初めて作成するユーザー インターフェース、権限、Android ファイルシステムでのファイル、Android マーケットでのアプリケーションなど)について教えてもらうことができます。新たに質問する前に、必ず最初にアーカイブを確認してください。高度な内容の質問の場合はここでは質問せず、android-developers メーリング リストで質問してください。また使用に関する質問は、android-discuss メーリング リストの方が適しています。
+<ul>
+<li>Google グループで登録:&nbsp;<a href="http://groups.google.com/group/android-beginners?hl=ja">android-beginners</a></li>
+<li>メールで登録:&nbsp;<a href="mailto:android-beginners-subscribe@googlegroups.com">android-beginners-subscribe@googlegroups.com</a><a href="mailto:android-platform-subscribe@googlegroups.com"> </a></li>
+</ul>
+</li>
+
+<li><b>Android デベロッパー向け</b> - Android アプリケーション デベロッパーとして経験を積むにつれ、Android アプリケーション開発の基本を把握して、SDK を使いこなせるようになります。今度は、より高度な内容について質問する必要があります。アプリケーションのトラブルシューティング、実装へのアドバイス、アプリケーションのパフォーマンスやユーザー エクスペリエンスを改良するテクニックに関する質問には、次のメーリング リストが役立ちます。使用に関する問題(android-discuss をご利用ください)や、Android SDK を使用する際の初歩的質問(android-beginners をご利用ください)についてのディスカッションの場所ではありません。
+<ul>
+<li>Google グループで登録:&nbsp;<a href="http://groups.google.com/group/android-developers?hl=ja">android-developers</a></li>
+<li>メールで登録:&nbsp;<a href="mailto:android-developers-subscribe@googlegroups.com">android-developers-subscribe@googlegroups.com</a><a href="mailto:android-platform-subscribe@googlegroups.com"> </a></li>
+</ul>
+</li>
+
+<li><b>Android ディスカッション</b> - Android に関する「井戸端会議」です。ここでは、Android プラットフォームへのアイデア、自分のアプリケーションの公表、Android 携帯端末に関するディスカッション、コミュニティ リソースなど、Android に関することなら何でも投稿可能です。ただし他のメーリング リストに該当する内容の場合は、そのメーリング リストに投稿することをおすすめします。質問のテーマが限定されている場所の方が、より多くの回答を得ることができるでしょう。
+<ul>
+<li>Google グループで登録:&nbsp;<a href="http://groups.google.com/group/android-discuss?hl=ja">android-discuss</a></li>
+<li>メールで登録:&nbsp;<a href="mailto:android-discuss-subscribe@googlegroups.com">android-discuss-subscribe@googlegroups.com</a><a href="mailto:android-platform-subscribe@googlegroups.com"> </a></li>
+</ul>
+</li>
+
+<li><b>Android セキュリティ ディスカッション</b> - 安全な開発、新たに発生したセキュリティの問題、Android デベロッパー向けの Android デベロッパーによるベスト プラクティスについて自由にディスカッションを行える場所です。メーリング リストで脆弱性を直接公開することは、すべての Android ユーザーを危険にさらすことになるので、避けてください。
+<ul>
+<li>Google グループで登録:&nbsp;<a href="http://groups.google.com/group/android-security-discuss?hl=ja">android-security-discuss</a></li>
+<li>メールで登録:&nbsp;<a href="mailto:android-security-discuss@googlegroups.com">android-security-discuss@googlegroups.com</a><a href="mailto:android-platform-subscribe@googlegroups.com"> </a></li>
+</ul>
+</li>
+
+<li><b>Android セキュリティに関する発表</b> - Android セキュリティ チームがセキュリティ関連の発表を行う、小規模なグループです。
+<ul>
+<li>Google グループで登録:&nbsp;<a href="http://groups.google.com/group/android-security-announce?hl=ja">android-security-announce</a></li>
+<li>メールで登録:&nbsp;<a href="mailto:android-security-announce-subscribe@googlegroups.com">android-security-announce-subscribe@googlegroups.com</a> <a href="mailto:android-platform-subscribe@googlegroups.com"> </a></li>
+</ul>
+</li>
+
+<li><b>Android マーケット ヘルプフォーラム</b> - Android マーケットに関する質問や問題の報告をするための、ウェブベースのディスカッション フォーラムです。
+<ul>
+<li>URL:&nbsp;<a href="http://www.google.com/support/forum/p/Android+Market?hl=ja">http://www.google.com/support/forum/p/Android+Market?hl=ja</a></li>
+</ul>
+</li>
+
+</ul>
+
+
+
+<h2 id="UsingEmail">メーリング リストにメールを使用</h2>
+<p><a href="http://groups.google.com/">Google グループ</a> のサイトを使用する代わりに、メール クライアントを使用して、メーリング リストに投稿することも可能です。</p>
+<p>Google グループのサイトを使用せずに、グループに登録するには、上記の「メールで登録」のリンクを使用します。</p>
+<p>メーリング リストへの投稿をメールで受信するように設定する方法は、次のとおりです:</p>
+
+<ol><li>Google グループ サイトから、グループにログインします。たとえば android-framework グループには <a href="http://groups.google.com/group/android-framework?hl=ja">http://groups.google.com/group/android-framework?hl=ja</a> にアクセスします。</li>
+<li>右側の [メンバーステータスを編集] をクリックします。</li>
+<li>[このグループの閲覧方法] で、メール オプションのいずれかを選択します。 </li>
+</ol>
+
+<h2 id="UsingIRC">IRC の使用</h2>
+<p>Android コミュニティは irc.freenode.net サーバーの #android チャンネルを使用しています。
+</p>
+
+
+
+
+
+
+
+</div>
diff --git a/docs/html/intl/ja/guide/basics/what-is-android.jd b/docs/html/intl/ja/guide/basics/what-is-android.jd
new file mode 100644
index 0000000..89558a0
--- /dev/null
+++ b/docs/html/intl/ja/guide/basics/what-is-android.jd
@@ -0,0 +1,81 @@
+page.title=Android とは
+@jd:body
+
+<p>Android は、オペレーティング システム、ミドルウェア、主要なアプリケーションを含む、携帯電話向けのソフトウェア スタックです。<a href="http://code.google.com/android/download.html">Android SDK</a> は、Java プログラミング言語を使用した Android プラットフォーム向けのアプリケーションの開発を始めるのに必要なツールと API を提供します。</p>
+
+<h2>特長</h2>
+
+<ul>
+    <li>コンポーネントの再利用と置換が可能な<strong>アプリケーション フレームワーク</strong></li>
+    <li>携帯電話用に最適化された <strong>Dalvik 仮想マシン</strong></li>
+    <li>オープンソース <a
+    href="http://webkit.org/">WebKit</a> エンジンをベースにした<strong>統合ブラウザ</strong> </li>
+    <li>カスタム 2D グラフィックス ライブラリと OpenGL ES 1.0 仕様に基づいた 3D グラフィックスにより提供される<strong>最適化されたグラフィックス</strong>(オプションのハードウェア アクセラレーション)</li>
+    <li><strong>SQLite</strong> による構造化データ ストレージ</li>
+    <li>音声、映像、静止画の一般的なフォーマット(MPEG4、H.264、MP3、AAC、AMR、JPG、PNG、GIF)に対する<strong>メディア サポート</strong></li>
+    <li><strong>GSM テレフォニー機能</strong>(ハードウェアに依存)</li>
+    <li><strong>Bluetooth、EDGE、3G、WiFi</strong>(ハードウェアに依存)</li>
+    <li><strong>カメラ、GPS、コンパス、加速度計</strong>(ハードウェアに依存)</li>
+    <li>デバイス エミュレータ、デバッグ用ツール、メモリとパフォーマンスの分析、Eclipse IDE 用プラグインを含む<strong>機能の豊富な開発環境</strong></li>
+</ul>
+
+<a name="os_architecture" id="os_architecture"></a>
+<h2>Android アーキテクチャ</h2> 
+
+<p>Android オペレーティング システムの主なコンポーネントを次の図に示します。それぞれのセクションには、各コンポーネントの詳細が記述されています。</p>
+
+<p><img src="{@docRoot}images/system-architecture.jpg" alt="Android システム アーキテクチャ" width="713" height="512"></p>
+
+<a name="applications" id="applications"></a>
+<h2>アプリケーション</h2>
+
+<p>Android には、メール クライアント、SMS プログラム、カレンダー、地図、ブラウザ、連絡先などのコア アプリケーションのセットが付属しています。アプリケーションはすべて Java プログラミング言語で作成されています。</p>
+
+<a name="application_framework" id="application_framework"></a>
+<h2>アプリケーション フレームワーク</h2>
+
+<p>デベロッパーは、コア アプリケーションによって使用されるフレームワーク API のすべてにアクセスできます。アプリケーション アーキテクチャは、コンポーネントの再利用を容易にするように設計されています。このため、どのアプリケーションも機能を公開し、別のアプリケーションがその機能を使用することが可能です(ただし、フレームワークによって実施されるセキュリティ制限の対象となります)。このメカニズムによって、ユーザーによるコンポーネントの入れ替えも可能です。</p>
+
+<p>アプリケーションの基盤となるのは、次のサービスとシステムのセットです:
+<ul>
+    <li>アプリケーションの構築を可能にする、拡張可能で豊富な<a
+    href="{@docRoot}guide/tutorials/views/index.html">ビュー</a>のセット。ビューには、リスト、グリッド、テキスト ボックス、ボタンだけでなく、埋め込み可能なウェブブラウザも含まれます。</li>
+    <li><a href="{@docRoot}guide/topics/providers/content-providers.html">コンテンツ プロバイダ</a>を使用すると、アプリケーションのデータ(たとえば、連絡先アプリケーション)に、別のアプリケーションからアクセスしたり、データを共有させることができます。</li> <li><a
+    href="{@docRoot}guide/topics/resources/resources-i18n.html">リソース マネージャ</a>は、ローカライズされた文字列、グラフィックス、レイアウト ファイルなどのコード以外のリソースへのアクセスを提供します。</li>
+    <li>{@link android.app.NotificationManager 通知マネージャ}を使用すると、すべてのアプリケーションからステータス バーにカスタマイズした警告を表示することができます。</li>
+    <li>{@link android.app.Activity アクティビティ マネージャ}は、アプリケーションのライフサイクルを管理し、共通のナビゲーション バックスタックを提供します。</li>
+</ul>
+
+<p>アプリケーションの簡単な説明と詳細については、<a
+href="{@docRoot}guide/tutorials/notepad/index.html">Notepad チュートリアル</a>をご覧ください。</p>
+    
+<a name="libraries" id="libraries"></a>
+<h2>ライブラリ</h2>
+
+<p>Android には C/C++ ライブラリのセットが含まれており、Android システムのさまざまなコンポーネントにおいて使用されています。これらの機能は、Android アプリケーション フレームワークを介して、デベロッパーに公開されています。コア ライブラリの一部を次に示します:</p>
+<ul>
+    <li><strong>システム C ライブラリ</strong> - BSD による実装をベースにした標準の C システム ライブラリ(libc)です。埋め込み Linux ベースのデバイス用に最適化されています。</li>
+    <li><strong>メディア ライブラリ</strong> - PacketVideo の OpenCORE をベースにしたライブラリです。MPEG4、H.264、MP3、AAC、AMR、JPG、PNG などの多くの一般的な映像と音声のフォーマットと、静止画ファイルの再生と記録をサポートしています。</li>
+    <li><strong>サーフェス マネージャ</strong> - 表示サブシステムへのアクセスを管理し、複数のアプリケーションからの 2D と 3D のグラフィック レイヤーをシームレスに合成します。</li>
+    <li><strong>LibWebCore</strong> - 最新式のウェブブラウザ エンジンで、Android ブラウザと埋め込み可能な Web 表示の両方を提供します。</li>
+    <li><strong>SGL</strong> - ベースとなる 2D グラフィックス エンジンです。</li>
+    <li><strong>3D ライブラリ</strong> - OpenGL ES 1.0 API をベースとして実装されたライブラリです。ハードウェア 3D アクセラレーション(可能な場合)か、高度に最適化された埋め込みの 3D ソフトウェア ラスタライザのいずれかを使用します。</li>
+    <li><strong>FreeType</strong> - ビットマップ フォントやベクタ フォントのレンダリングを行います。</li>
+    <li><strong>SQLite</strong> - すべてのアプリケーションで利用可能な強力で軽量のリレーショナル データベース エンジンです。</li>
+</ul>
+
+<a name="runtime" id="runtime"></a>
+
+<h2>Android ランタイム</h2>
+
+<p>Android には、Java プログラミング言語のコア ライブラリで利用できる機能のほとんどを提供するコア ライブラリのセットが含まれています。</p>
+
+<p>Android の各アプリケーションは、独自のプロセスとして実行され、Dalvik 仮想マシン(VM)の独自のインスタンスにより実行されます。Dalvik は、携帯電話で複数の VM を効率よく実行できるように設計されています。Dalvik VM は、メモリの使用量を最小にするように最適化された Dalvik 実行可能(.dex)フォーマットのファイルを実行します。この VM はレジスタベースであり、Java 言語コンパイラによりコンパイルされた組み込みの「dx」ツールにより .dex フォーマットに変換されたクラスを実行します。</p>
+
+<p>Dalvik VM は、Linux カーネルを使用して、スレッディングや低レベルのメモリ管理などの基本機能を実行しています。</p>
+
+<a name="kernel" id="kernel"></a>
+
+<h2>Linux カーネル</h2>
+
+<p>Android は、Linux バージョン 2.6 を使用して、セキュリティ、メモリ管理、プロセス管理、ネットワーク スタック、ドライバ モデルなどのコア システム サービスを提供します。このカーネルは、ハードウェアと他のソフトウェア スタックの間の抽象化レイヤーとしても機能します。</p>
diff --git a/docs/html/intl/ja/guide/developing/eclipse-adt.jd b/docs/html/intl/ja/guide/developing/eclipse-adt.jd
new file mode 100644
index 0000000..26cae54
--- /dev/null
+++ b/docs/html/intl/ja/guide/developing/eclipse-adt.jd
@@ -0,0 +1,243 @@
+page.title=Eclipse 内で ADT を使用
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+  <h2>このドキュメントの内容</h2>
+  <ol>
+    <li><a href="#CreatingAProject">Android プロジェクトの作成</a></li>
+    <li><a href="#Running">アプリケーションの実行</a>
+  <ol>
+ <li><a href="#CreatingAnAvd">AVD の作成</a></li>
+ <li><a href="#RunningAnApplication">アプリケーションの実行</a></li>
+  </ol>
+    </li>
+    <li><a href="#RunConfig">カスタム起動構成の作成</a></li>
+    <li><a href="#Signing">アプリケーションの署名設定</a></li>
+    <li><a href="#Tips">Eclipse のヒント</a></li>
+  </div>
+</div>
+
+
+<p>「Android Development Tools (ADT) plugin for Eclipse」は、Eclipse 統合開発環境に強力な拡張機能を追加します。拡張機能により、Android アプリケーションの作成とデバッグが容易になります。Eclipse を使用している場合、ADT プラグインを組み込むことで、Android アプリケーションを驚くほど効率よく開発できるようになります:</p>
+
+<ul>
+  <li>Eclipse 総合開発環境内から、他の Android 開発ツールにもアクセスできます。たとえば ADT では、DDMS ツールの多くの機能が利用できます。Eclipse からスクリーンショットの撮影、ポート転送の管理、ブレークポイントの設定、スレッドやプロセスの情報の表示を直接行うことが可能です。</li>
+  <li>Android 開発用の新たなプロジェクト ウィザードが追加されます。それを使用して、新しい Android アプリケーションに必要な基本ファイルをすべて簡単に作成してセットアップできます。</li>
+  <li>Android アプリケーションのビルド プロセスを自動化と単純化できます。</li>
+  <li>同梱の Android コード エディタを使用して、Android のマニフェスト ファイルとリソース ファイルの適切な XML をスムーズに作成できます。</li>
+  <li>プロジェクトを、ユーザーに配布可能な署名済みの APK 形式でエクスポートすることもできます。</li>
+</ul>
+
+<p>ADT を組み込んだ Eclipse 総合開発環境で Android アプリケーションの開発を始めるには、最初に Eclipse 総合開発環境をダウンロードしてから、ADT プラグインをダウンロードしてインストールする必要があります。そのためには、<a href="{@docRoot}sdk/{@sdkCurrent}/installing.html#installingplugin">Eclipse 用 ADT プラグインのインストール</a>に記載されている手順どおりに操作します。</p>
+<p>バージョン 0.9 より前の ADT を使用してアプリケーションを既に開発中の場合は、必ず最新バージョンにアップグレードしてから続行してください。<a href="{@docRoot}sdk/{@sdkCurrent}/upgrading.html#UpdateAdt">Eclipse ADT プラグインをアップデート</a>するためのガイドをご覧ください。</p>
+<p class="note"><strong>注:</strong> このガイドでは、ADT プラグインの最新バージョンを使用していることを前提としています。説明の大半は、以前のバージョンにも当てはまりますが、以前のバージョンを使用している場合は、このドキュメントのオンライン版ではなく、SDK パッケージに付属された資料内の同ドキュメントをご覧ください。</p>
+
+
+<h2  id="CreatingAProject">Android プロジェクトの作成</h2>
+
+<p>ADT プラグインが提供する新規プロジェクト ウィザードを使用すると、簡単に Android プロジェクトを新規作成(または既存のコードから作成)できるようになります。新しいプロジェクトを作成するには: </p>
+
+<ol>
+  <li>[<strong>ファイル(File)</strong>] &gt; [<strong>新規(New)</strong>] &gt; [<strong>プロジェクト(Project)</strong>] を選択します。</li>
+  <li>[<strong>Android</strong>] &gt; [<strong>Android プロジェクト(Android Project)</strong>] を選択し、[<strong>次へ(Next)</strong>] をクリックします。</li>
+  <li>プロジェクトの内容を選択します:
+    <ul>
+  <li>プロジェクト名を入力します。<em></em>これはそのプロジェクトが作成されるフォルダの名前になります。</li>  <li>[内容(Contents)] セクションで、[<strong>ワークスペース内に新規プロジェクトを作成(Create new project in workspace</strong>] を選択します。プロジェクト ワークスペースのロケーションを選択します。</li>
+  <li>[ターゲット(Target)] タブで、プロジェクトの [ビルド ターゲット(Build Target)] として使用する Android ターゲットを選択します。このビルド ターゲットは、アプリケーションをビルドする Android プラットフォームを指定します。
+ <p>最新の SDK に導入されている新しい API を使用することがわかっている場合を除き、Android 1.1 などの最も古いバージョンのターゲット (Target Name) を選択してください。</p>
+ <p class="note"><strong>注:</strong> プロジェクトのビルド ターゲットはいつでも変更できます。変更するには、[パッケージ エクスプローラー(Package Explorer)] でプロジェクトを右クリックし、[<strong>プロパティ(Properties)</strong>] を選択し、[<strong>Android</strong>] を選択して、指定するプロジェクト ターゲットのチェックボックスをオンにします。</p>
+  </li>
+  <li>[プロパティ(Properties)] セクションで、必要なすべてのフィールドに入力します。
+ <ul>
+   <li>アプリケーション名 (Application name) を入力します。<em></em>アプリケーション名はユーザーにわかりやすいアプリケーションのタイトルにします。この名前が Android 携帯端末に表示されます。</li>
+   <li>パッケージ名 (Package name) を入力します。<em></em>これは(Java プログラミング言語でのパッケージのルールに従った)パッケージの名前空間であり、作成するソース コードはすべてこの中に含まれます。</li>
+   <li>[Activity を作成(Create Activity)] を選択し(オプションですが、一般的な手順です)、メインの Activity クラスの名前を入力します。<em></em></li>
+   <li>[SDK の最小バージョン(Min SDK Version)] を入力します。<em></em>これは、そのアプリケーションを正常に実行するために必要となる API の最小レベルを示す番号です。ここで入力すると、<code>minSdkVersion</code> 属性が Android マニフェスト ファイルの <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a> に自動的に設定されます。使用する適切な API レベルがわからない場合は、ビルド ターゲット(Build Target)にリストされている API レベル(API Level)をコピーします。</li>
+ </ul>
+  </li>
+    </ul>
+  </li>
+  <li>[<strong>完了(Finish)</strong>] をクリックします。</li>
+</ol>
+
+<p class="note"><strong>ヒント:</strong> 新規プロジェクト ウィザードは、ツールバーの [新規(New)] アイコンからも開始できます。<em></em></p>
+
+<p>新規プロジェクト ウィザードを完了すると、ADT は新しいプロジェクトに次のフォルダとファイルを作成します:</p>
+  <dl>
+    <dt><code>src/</code></dt>
+  <dd>スタブ Activity Java ファイルが含まれます。アプリケーションの他のすべての Java ファイルも含まれます。</dd>
+    <dt><code><em>&lt;Android Version&gt;</em>/</code>(例: <code>Android 1.1/</code>)</dt>
+  <dd>アプリケーションのビルド対象となる <code>android.jar</code> ファイルが含まれます。これは、新規プロジェクト ウィザードで選択したビルド ターゲットによって決まります。<em></em></dd>
+    <dt><code>gen/</code></dt>
+  <dd>ADT により生成された Java ファイル(<code>R.java</code> ファイル、AIDL ファイルから作成されたインターフェースなど)がこのフォルダに含まれます。</dd>
+    <dt><code>assets/</code></dt>
+  <dd>このフォルダは空です。未加工のアセット ファイルの保存に使用できます。<a href="{@docRoot}guide/topics/resources/index.html">Resources and Assets</a>をご覧ください。</dd>
+    <dt><code>res/</code></dt>
+  <dd>アプリケーションのリソース用(描画ファイル、レイアウト ファイル、文字列値など)のフォルダです。<a href="{@docRoot}guide/topics/resources/index.html">Resources and Assets</a>をご覧ください。</dd>
+    <dt><code>AndroidManifest.xml</code></dt>
+  <dd>このプロジェクトの Android マニフェストです。<a href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a>をご覧ください。</dd>
+    <dt><code>default.properties</code></dt>
+  <dd>このファイルには、ビルド ターゲットのようなプロジェクトの設定が含まれます。このファイルはプロジェクトに不可欠なので、ソース リビジョン管理システムで管理する必要があります。このファイルを手動で編集しないでください。プロジェクトのプロパティを編集するには、プロジェクト フォルダを右クリックして、[プロパティ(Properties)] を選択します。</dd>
+  </dl>
+
+
+<h2 id="Running">アプリケーションの実行</h2>
+
+<p>注意してください。<em></em>アプリケーションを Android エミュレータで実行する前に、Android 仮想デバイス(AVD)を作成する<strong>必要があります</strong>。AVD では、エミュレータで使用する Android プラットフォームを指定します。詳しくは <a href="{@docRoot}guide/developing/tools/avd.html">Android 仮想デバイス</a> のドキュメントをご覧ください。ただし、すぐにアプリケーションを実行したい場合は、次の簡単な手順に従って AVD を作成してください。</p>
+
+<p>携帯端末の実機でのみアプリケーションを実行する場合は、AVD は必要ありません。この場合のアプリケーションの実行について詳しくは、<a href="{@docRoot}guide/developing/device.html">Developing On a Device</a> をご覧ください。</p>
+
+<h3 id="CreatingAnAvd">AVD の作成</h3>
+
+<p>詳しい説明はこのドキュメントの範囲外なので、AVD を作成する基本的な手順のみをここに示します:</p>
+
+<ol>
+  <li>コマンドライン(たとえば Windows では「コマンド プロンプト」アプリケーション、Mac/Linux では「ターミナル」)を開き、SDK パッケージの <code>tools/</code> ディレクトリに移動します。</li>
+  <li>最初に、配備ターゲットを選択する必要があります。選択可能なターゲットを表示するには、次のコマンドを実行します:
+    <pre>android list targets</pre>
+    <p>次のように選択可能な Android ターゲットのリストが表示されます:</p>
+<pre>
+id:1
+    Name: Android 1.1
+    Type: platform
+    API level: 2
+    Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P
+id:2
+    Name: Android 1.5
+    Type: platform
+    API level: 3
+    Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P
+</pre>
+    <p>アプリケーションを実行する Android プラットフォームに一致するターゲットを探します。<code>id</code> の整数を書き留めておき、次のステップで使用します。</p>
+  </li>
+  <li>選択した配備ターゲットを使用して、新しい AVD を作成します。次のコマンドを実行します:
+    <pre>android create avd --name <em>&lt;your_avd_name&gt;</em> --target <em>&lt;targetID&gt;</em></pre>
+  <li>カスタム ハードウェア プロファイルを作成するかどうかの問い合わせがあります。「yes」と答えると、携帯端末ハードウェアのさまざまな要素を定義するための一連のプロンプトが開始されます(空白のまま入力すると、かっこ内に表示されたデフォルト値が使用されます)。または、Enter キーを押すと、すべてデフォルト値が使用されます(「no」がデフォルトです)。</li>
+  </li>
+</ol>
+
+<p>これで AVD が作成できました。次のセクションでは、エミュレータでアプリケーションを起動する際に、AVD がどのように使用されるかについて説明します。</p>
+
+<p>AVD の作成と管理について詳しくは、<a href="{@docRoot}guide/developing/tools/avd.html">Android 仮想デバイス</a> のドキュメントをご覧ください。</p>
+
+
+<h3 id="RunningYourApplication">アプリケーションの実行</h3>
+
+<p class="note"><strong>注:</strong> アプリケーションを実行する前に、アプリケーションのビルド ターゲットを満たすターゲットを指定した AVD を必ず作成してください。ビルド ターゲットの要件を満たす AVD が見つからない場合、それを示すコンソール エラーが表示され、起動は中止されます。</p>
+
+<p>アプリケーションを実行(またはデバッグ)するには、Eclipse のメイン メニューで [<strong>実行(Run)</strong>] &gt; [<strong>実行(Run)</strong>](または [<strong>実行(Run)</strong>] &gt; [<strong>デバッグ(Debug)</strong>])を選択します。ADT プラグインはそのプロジェクトのデフォルトの起動構成を自動的に作成します。</p>
+
+<p>アプリケーションの実行またはデバッグを選択すると、Eclipse では以下が行われます:</p>
+
+<ol>
+  <li>プロジェクトがコンパイルされます(最後のビルド以降、変更があった場合)。</li>
+  <li>デフォルトの起動構成が作成されます(そのプロジェクトでまだ作成されていない場合)。</li>
+  <li>エミュレータまたは端末(起動構成で定義された配備ターゲットに基づきます)にアプリケーションがインストールされ、起動されます。
+    <p>デフォルトでは、Android アプリケーションの起動構成ではデバイス ターゲットの選択に「自動ターゲット」モードを使用します。自動ターゲット モードでの配備ターゲットの選択について詳しくは、下記の<a href="#AutoAndManualTargetModes">自動または手動のターゲット モード</a>をご覧ください。</p>
+  </li>
+</ol>
+
+<p>デバッグの場合は、アプリケーションは「デバッガ待ち」モードで開始されます。デバッガの接続後、Eclipse はデバッグ パースペクティブを開きます。</p>
+
+<p>プロジェクトで使用する起動構成を設定または変更するには、構成マネージャを使用します。詳しくは<a href="#launchconfig">起動構成の作成</a>をご覧ください。</p>
+
+
+<h2 id="RunConfig">起動構成の作成</h2>
+
+<p>起動構成では、実行するプロジェクト、開始する Activity、使用するエミュレータ オプションなどを指定します。プロジェクトを初めて Android アプリケーションとして実行すると、ADT は自動的に起動構成を作成します。<em></em>デフォルトの起動構成は、デフォルトのプロジェクト アクティビティを起動し、自動ターゲット モードで端末を選択します(優先 AVD が指定されていない場合)。デフォルト設定がプロジェクトに適さない場合は、起動構成をカスタマイズするか、新規作成することができます。</p>
+
+<p>起動構成を作成または変更するには、使用している Eclipse のバージョンに合わせて、次の手順どおりに操作します:</p>
+
+<ol>
+  <li>構成マネージャを開きます。
+ <ul>
+   <li>Eclipse 3.3(Europa)では、[<strong>実行(Run)</strong>] &gt; [<strong>実行ダイアログを開く(Open Run Dialog)</strong>](または [<strong>デバッグ ダイアログを開く(Open Debug Dialog)</strong>])を選択します。
+   </li>
+   <li>Eclipse 3.4(Ganymede)では、[<strong>Run(実行)</strong>] &gt; [<strong>実行の構成(Run Configurations)</strong>](または [<strong>デバッグの構成(Debug Configurations)</strong>])を選択します。
+   </li>
+  </ul>
+  </li>
+  <li>[<strong>Android アプリケーション(Android Application)</strong>] 項目を展開し、新しい構成を作成するか、既存の構成を開きます。
+    <ul>
+  <li>新しい構成を作成するには: 
+ <ol>
+   <li>[<strong>Android アプリケーション(Android Application)</strong>] を選択し、<em></em>リストの上にある 新規起動の構成(New launch configuration) アイコンをクリックします(または [<strong>Android アプリケーション(Android Application)</strong>] を右クリックして、[<strong>新規(New)</strong>] をクリックします)。</li>
+   <li>この構成の名前を入力します。</li>
+   <li>[Android] タブで、この構成を使用して実行するプロジェクトを参照し、選択します。</li>
+ </ol>
+  <li>既存の構成を開くには、[<strong>Android アプリケーション(Android Application)</strong>] の下にネストされているリストからその構成名を選択します。</li>
+    </ul>
+  </li>
+  <li>必要に応じて起動構成の設定を変更します。
+    <p>[ターゲット(Target)] タブでは、アプリケーションを実行する AVD の選択を手動(Manual)モードで行うか、自動(Automatic)モードで行うかを考えます(次の<a href=#AutoAndManualModes">自動または手動のターゲット モード</a>のセクションをご覧ください)。</p>
+  </li>
+</ol>
+
+
+<h3 id="AutoAndManualTargetModes">自動または手動のターゲット モード</h3>
+
+<p>デフォルトでは、起動構成には、<strong>自動</strong>ターゲット モードで選択された AVD が使用されます。このモードでは、ADT は次の方法により、アプリケーションの AVD を選択します:</p>
+
+<ol>
+  <li>既に実行中の端末またはエミュレータがあり、その AVD 構成がアプリケーションのビルド ターゲットの要件を満たす場合は、その端末またはエミュレータにアプリケーションがインストールされ、実行されます。</li>
+  <li>端末またはエミュレータが複数実行中の場合は、そのうちのビルド ターゲットの要件を満たすものが「デバイス選択(Device Chooser)」に表示されるので、その中から選択できます。</li>
+  <li>ビルド ターゲットの要件を満たす実行中の端末やエミュレータがない場合は、ADT は使用可能な AVD を調べます。ビルド ターゲットの要件を満たす AVD があれば、その AVD を使用して新しいエミュレータが起動され、そこにアプリケーションがインストールされ、実行されます。</li>
+  <li>上記を満たすものがない場合は、アプリケーションは実行されず、ビルド ターゲット要件を満たす既存の AVD がないというエラーがコンソールに表示されます。</li>
+</ol>
+
+<p>ただし起動構成で「優先 AVD」が選択されている場合は、アプリケーションは常にその AVD に配備されます。<em></em>その AVD がまだ実行されていない場合は、新しいエミュレータが起動されます。</p>
+<p>起動構成が<strong>手動</strong>モードの場合は、アプリケーションを実行するたびに、「Device Chooser」が表示されるので、使用する AVD を選択できます。</p>
+
+<h2 id="Signing">アプリケーションへの署名</h2>
+
+<p>Android アプリケーションの開発を始めると、Android アプリケーションをシステムがエミュレータや実機にインストールする前に、どの Android アプリケーションにもデジタル署名が必要であることがわかります。署名には、デバッグ キーを使用する方法(エミュレータや開発用端末ですぐにテストする場合)と、非公開キーを使用する方法(アプリケーションを配布する場合)の 2 つがあります。</p>
+<p>ADT プラグインでは、アプリケーションをエミュレータや開発用端末にインストールする前に、.apk ファイルがデバッグ キーを使用して署名されるので、開発を早めることができます。つまり、独自の非公開キーを生成する必要がなく、Eclipse からアプリケーションをすぐに実行できます。Keytool に ADT がアクセスできれば、デベロッパーが特に操作する必要はありません。ただし、アプリケーションを公開する場合は、SDK ツールが生成するデバッグ キーではなく、独自の非公開キーを使用してアプリケーションに署名する<strong>必要があります</strong>。</p>
+<p><a href="{@docRoot}guide/publishing/app-signing.html">アプリケーションへの署名</a>をご覧ください。Android でのアプリケーションへの署名と、Android アプリケーション デベロッパーにとっての署名の意味について説明しています。このドキュメントには、ADT のエクスポート ウィザードを使用してアプリケーションをエクスポートし、署名するためのガイドも含まれています。</p>
+
+<h2 id="Tips">Eclipse のヒント </h2>
+
+<h3 id="arbitraryexpressions">Eclipse での任意の Java コードの実行</h3>
+
+<p>Eclipse のブレークポイントで中断したとき、任意のコードを実行できます。たとえば「zip」という文字列引数を使用する関数では、パッケージと呼び出しクラスのメソッドに関する情報を取得できます。任意の静的メソッドを呼び出すこともできます。たとえば <code>android.os.Debug.startMethodTracing()</code> と入力すると、dmTrace が起動されます。 </p><p>コードの実行ウィンドウを開き、メイン メニューから [<strong>ウィンドウ(Window)</strong>] &gt; [<strong>ビューの表示(Show View)</strong>] &gt; [<strong>表示(Display)</strong>] を選択すると、簡単なテキスト エディタである [表示(Display)] ウィンドウが開きます。式を入力し、そのテキストをハイライト表示し、'J' アイコンをクリックして(または Ctrl+Shift+D キーを押して)そのコードを実行します。コードは、選択したスレッド(ブレークポイントまたはシングルステップ ポイントで停止している必要があります)のコンテキストで実行されます(手動でスレッドを強制停止した場合は、シングルステップを 1 回実行する必要があります。スレッドが Object.wait() 状態の場合は、上記を実行できません)。</p><p>現在、ブレークポイントで中断している場合は、ソース コードの一部をハイライト表示し、Ctrl+Shift+D キーを押して実行することができます。 </p><p>同じスコープ内のテキストの一部をハイライト表示するには、Alt+Shift+上矢印キーを押して、より広い範囲の閉じたブロック(複数可)を選択するか、下矢印キーを押して選択範囲を小さくすることができます。 </p><p>Eclipse で [表示(Display)] ウィンドウを使用した入力とその応答のサンプルを次に示します。</p>
+
+<table width="100%" border="1">
+    <tr>
+ <th scope="col">入力</th>
+ <th scope="col">応答</th>
+    </tr>
+    <tr>
+ <td><code>zip</code></td>
+ <td><code>(java.lang.String) 
+ /work/device/out/linux-x86-debug/android/app/android_sdk.zip</code></td>
+    </tr>
+    <tr>
+ <td><code>zip.endsWith(&quot;.zip&quot;)</code></td>
+ <td><code>(boolean) true</code></td>
+    </tr>
+    <tr>
+ <td><code>zip.endsWith(&quot;.jar&quot;)</code></td>
+ <td><code>(boolean) false</code></td>
+    </tr>
+</table>
+<p>デバッガではなくスクラップブック ページを使用しても、任意のコードを実行できます。Eclipse ドキュメントで「スクラップブック」を検索してください。</p>
+
+<h3>DDMS の手動による実行</h3>
+
+<p>ADT プラグインを使用するデバッグをおすすめしますが、手動で DDMS を実行し、ポート 8700 でデバッグするように Eclipse を設定することができます(<strong>注:</strong> 最初に必ず <a href="{@docRoot}guide/developing/tools/ddms.html">DDMS</a> を起動してください)。 </p>
+
+<!-- TODO: clean this up and expand it to cover more wizards and features
+<h3>ADT Wizards</h3>
+
+<p>Notice that the "New Android Project" wizard has been expanded to use the multi-platform
+capabilities of the new SDK.</p>
+
+<p>There is now a "New XML File" wizard that lets you create skeleton XML resource
+files for your Android projects. This makes it easier to create a new layout, a new menu, a
+new strings file, etc.</p>
+
+<p>Both wizards are available via <strong>File > New</strong> and new icons in the main
+Eclipse toolbar (located to the left of the Debug and Run icons). 
+If you do not see the new icons, you may need to select <strong>Window > Reset
+Perspective</strong> from the Java perspective.</p>
+-->
diff --git a/docs/html/intl/ja/guide/developing/other-ide.jd b/docs/html/intl/ja/guide/developing/other-ide.jd
new file mode 100644
index 0000000..2983da2
--- /dev/null
+++ b/docs/html/intl/ja/guide/developing/other-ide.jd
@@ -0,0 +1,271 @@
+page.title=その他の統合開発環境
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>このドキュメントの内容</h2>
+  <ol>
+    <li><a href="#CreatingAProject">Android プロジェクトの作成</a></li>
+    <li><a href="#Signing">アプリケーションへの署名の準備</a></li>
+    <li><a href="#Building">アプリケーションのビルド</a>
+      <ol>
+        <li><a href="#DebugMode">デバッグ モードでのビルド</a></li>
+        <li><a href="#ReleaseMode">リリース モードでのビルド</a></li>
+      </ol>
+    </li>
+    <li><a href="#Running">アプリケーションの実行</a></li>
+    <li><a href="#AttachingADebugger">アプリケーションへのデバッガの接続</a></li>
+  </ol>
+
+  <h2>関連項目</h2>
+  <ol>
+    <li><a href="{@docRoot}guide/developing/tools/othertools.html#android">android ツール</a></li>
+    <li><a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a></li>
+    <li><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a></li>
+  </ol>
+</div>
+</div>
+
+<p>Android アプリケーションの開発では、<a href="{@docRoot}guide/developing/eclipse-adt.html">ADT プラグイン搭載の Eclipse</a> を使用する開発方法が推奨されています。ADT プラグインは、編集、ビルド、デバッグ、.apk パッケージング、署名の機能を統合開発環境に直接統合して提供します。</p>
+
+<p>しかし Eclipse の代わりに IntelliJ のような別の総合開発環境や Emacs のような基本的なエディタを使用した開発も可能です。SDK には Android プロジェクトのセットアップ、ビルド、デバッグ、および配布用パッケージ作成に必要なすべてのツールが含まれています。このドキュメントでは、こうしたツールの使用方法について説明します。</p>
+
+
+<h2 id="EssentialTools">主要なツール</h2>
+
+<p>Eclipse 以外の統合開発環境やエディタで開発する際には、次の Android SDK ツールについて知っておく必要があります:</p>
+
+<dl>
+  <dt><a href="{@docRoot}guide/developing/tools/othertools.html#android">android</a></dt>
+    <dd>Android プロジェクトの作成/更新、AVD の作成/移動/削除のために使用します。</dd>
+  <dt><a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a></dt>
+    <dd>Android のエミュレーション プラットフォームで Android アプリケーションを実行するために使用します。</dd>
+  <dt><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a></dt>
+    <dd>エミュレータまたは接続先の端末とのインターフェースとして使用します(アプリケーションのインストール、端末のシェル、コマンドの実行などに使用)。
+    </dd>
+</dl>
+
+<p>上記のツールに加えて、SDK に含まれている次のオープンソースとおよびサードパーティ製のツールを使用します:</p>
+
+<dl>
+  <dt>Ant</dt>
+    <dd>Android プロジェクトをコンパイルし、インストール可能な .apk ファイルにビルドするために使用します。</dd>
+  <dt>Keytool</dt>
+    <dd>.apk ファイルに署名するために使用するキーストアと非公開キーを生成します。</dd>
+  <dt>Jarsigner(または同様の署名ツール)</dt>
+    <dd>Keytool で生成した非公開キーを使って .apk ファイルに署名するために使用します。</dd>
+</dl>
+
+<p>下記のトピックでは、必要な箇所でそれぞれの各ツールを説明しています。さらに高度な操作については、ツールのそれぞれのドキュメントをご覧ください。</p>
+
+
+<h2 id="CreatingAProject">Android プロジェクトの作成</h2>
+
+<p>Android プロジェクトを作成するには、<code>android</code> ツールを使用する必要があります。新しいプロジェクトを <code>android</code> で作成すると、デフォルトのアプリケーション ファイル、スタブ ファイル、構成ファイル、ビルド ファイルを含むプロジェクト ディレクトリが生成されます。</p>
+
+
+<h3 id="CreatingANewProject">新しいプロジェクトの作成</h3>
+
+<p>新しいプロジェクトを開始する場合、<code>android create project</code> コマンドを使用すると、必要なファイルとフォルダがすべて生成されます。</p>
+
+<p>新しい Android プロジェクトを作成するには、コマンドラインを開き、SDK の <code>tools/</code> ディレクトリに移動して、次を実行します:</p>
+<pre>
+android create project \
+--target <em>&lt;targetID&gt;</em> \
+--path <em>/path/to/your/project</em> \
+--activity <em>&lt;your_activity_name&gt;</em> \
+--package <em>&lt;your_package_namespace&gt;</em>
+</pre>
+
+<ul>
+  <li><code>target</code> は、アプリケーションの「ビルド ターゲット」です。これは、プロジェクトをビルドする Android プラットフォーム ライブラリ(Google API のようなアドオンも含まれます)に対応します。使用可能なターゲットとそれに対応する ID の一覧を表示するには、<code>android list targets</code> を実行します。</li>
+  <li><code>path</code> は、プロジェクト ディレクトリのロケーションです。このディレクトリが存在しない場合は、自動的に作成されます。</li>
+  <li><code>activity</code> は使用する {@link android.app.Activity} クラスの名前です。このクラス ファイルは <code><em>&lt;path_to_your_project&gt;</em>/src/<em>&lt;your_package_namespace_path&gt;</em>/</code> 内に作成されます。</li>
+  <li><code>package</code> はプロジェクトのパッケージ名前空間であり、Java プログラミング言語でのパッケージと同じルールに従います。</li>
+</ul>
+
+<p>次に例を示します:</p>
+<pre>
+android create project \
+--target 1 \
+--path ./myProject \
+--activity MyActivity \
+--package com.example.myproject
+</pre>
+
+<p>このツールは次のファイルとディレクトリを生成します:</p>
+
+<ul>
+  <li><code>AndroidManifest.xml</code> - アプリケーションのマニフェスト ファイル。指定したプロジェクトの Activity クラスと同期されます。</li>
+  <li><code>build.xml</code> - Ant 用のビルド ファイルです。</li>
+  <li><code>default.properties</code> - ビルド システム用のプロパティです。このファイルを変更しないでください。<em></em></li>
+  <li><code>build.properties</code> - ビルド システム用のカスタマイズ可能なプロパティです。このファイルを編集して、Ant が使用するデフォルトのビルド設定をオーバーライドできます。</li>
+  <li><code>src<em>/your/package/namespace/ActivityName</em>.java</code> - プロジェクトの作成時に指定した Activity クラスです。</li>
+  <li><code>bin/</code> - ビルド スクリプト用の出力ディレクトリです。</li>
+  <li><code>gen/</code> - <code>Ant</code> が生成するファイル(<code>R.java</code> など)が含まれます。 </li>
+  <li><code>libs/</code> - プライベート ライブラリが含まれます。</li>
+  <li><code>res/</code> - プロジェクト リソースが含まれます。</li>
+  <li><code>src/</code> - ソース コードが含まれます。</li>
+  <li><code>tests/</code> - テスト用に、上記のすべての複製が含まれます。</li>
+</ul>
+
+<p>プロジェクトを作成すると、開発を始める準備ができます。開発のために、プロジェクト フォルダをどこにでも移動できますが、アプリケーションをエミュレータに送信するために(方法については後述します)、SDK の <code>tools/</code> ディレクトリにある <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a>(adb)を使用する必要があります。そのためにプロジェクト ソリューションと <code>tools/</code> フォルダ間でアクセスする必要があります。</p>
+
+<p class="warning"><strong>注:</strong> SDK ディレクトリは移動させないでください。移動するとビルド スクリプトが機能しなくなります(ビルド スクリプトをもう一度機能させるには、手動でスクリプトを更新して、SDK の新しいロケーションを反映させる必要があります)。</p>
+
+
+<h3 id="UpdatingAProject">プロジェクトの更新</h3>
+
+<p>Android SDK の古いバージョンからプロジェクトをアップグレードする場合や、既存のコードから新しいプロジェクトを作成する場合は、<code>android update project</code> コマンドを使って新しい開発環境に合わせてプロジェクトを更新します。このコマンドを使って(<code>--target</code> オプションにより)、既存のプロジェクトのビルド ターゲットを修正することもできます。<code>android</code> ツールは、指定された Android プロジェクトの必要に応じて、欠落している、または更新を必要としているファイルやフォルダの生成を行います。生成物は前セクションに記述されたリストどおりです。</p>
+
+<p>既存の Android プロジェクトを更新するには、コマンドラインを開き、SDK の <code>tools/</code> ディレクトリに移動します。ここで次を実行します:</p>
+<pre>
+android update project --target <em>&lt;targetID&gt;</em> --path <em>path/to/your/project/</em>
+</pre>
+
+<ul>
+  <li><code>target</code> は、アプリケーションの「ビルド ターゲット」です。これは、プロジェクトをビルドする Android プラットフォーム ライブラリ(Google API のようなアドオンも含まれます)に対応します。使用可能なターゲットとそれに対応する ID の一覧を表示するには、<code>android list targets</code> を実行します。</li>
+  <li><code>path</code> は、プロジェクト ディレクトリのロケーションです。</li>
+</ul>
+
+<p>次に例を示します:</p>
+<pre>
+android update project --target 2 --path ./myProject
+</pre>
+
+
+<h2 id="Signing">アプリケーションへの署名の準備</h2>
+
+<p>Android アプリケーションの開発を始めると、Android アプリケーションをエミュレータや端末上のシステムにインストールする前に、どの Android アプリケーションにもデジタル署名が必要であることがわかります。解決策としては「デバッグ キー」を使用する方法(エミュレータや開発用端末上ですぐにテストする場合)と、非公開キーを使用する方法(アプリケーションを配布する場合)の 2 つがあります。<em></em><em></em></p>
+
+<p>Android のビルド ツールを使用すると、ビルド時にデバッグキーを使用して .apk ファイルに自動的に署名できるので、スムーズな開発が可能です。つまり、独自の非公開キーを生成しなくても、アプリケーションをコンパイルして、エミュレータにインストールすることができます。ただし、アプリケーションを公開する場合は、SDK ツールが生成したデバッグ キーではなく、独自の非公開キーを使用してアプリケーションに署名する<strong>必要があります</strong>。 </p>
+
+<p><a href="{@docRoot}guide/publishing/app-signing.html">アプリケーションへの署名</a>をご覧ください。Android でのアプリケーションへの署名と、Android アプリケーション デベロッパーにとっての署名の意味について説明しています。</p>
+
+
+
+<h2 id="Building">アプリケーションのビルド</h2>
+
+<p>アプリケーションのビルドには、アプリケーションをテスト/デバッグするための「デバッグ モード」と、リリース用の最終パッケージをビルドするための「リリース モード」の 2 つがあります。<em></em><em></em>前のセクションで説明したように、アプリケーションをエミュレータや端末にインストールする前に、アプリケーションに署名する必要があります。</p>
+
+<p>デバッグ モードとリリース モードのどちらでビルドしているかに関係なく、プロジェクトをコンパイルし、ビルドするには Ant ツールが必要です。これにより、エミュレータや端末にインストールする .apk ファイルが作成されます。デバッグ モードでビルドすると、.apk ファイルは SDK ツールによりデバッグ キーを使用して自動的に署名されるので、インストールの準備がすぐに整います(ただし、エミュレータまたは接続された開発用端末上にのみインストールできます)。リリース モードでビルドされた .apk ファイルは署名されないので、Keytool と Jarsigner を使って、独自の非公開キーで手動で署名する必要があります。<em></em></p>
+
+<p><a href="{@docRoot}guide/publishing/app-signing.html">アプリケーションへの署名</a>の内容をよく理解する必要があります。また、アプリケーションをリリースしてエンドユーザーと共有することを計画している場合は非常に重要です。「アプリケーションへの署名」では、非公開キーを生成し、それを使用して .apk ファイルに署名する手順について説明しています。ただし、開発を始めたばかりであれば、デバッグ モードでビルドすることにより、エミュレータまたは独自の開発用端末でアプリケーションをすぐに実行できます。</p>
+
+<p>Ant をお持ちでない場合は、<a href="http://ant.apache.org/">Apache Ant ホームページ</a>から入手してください。Ant をインストールして、必ず実行可能パスに置きます。Ant を実行する前に、「JAVA_HOME」環境変数を宣言して JDK のインストールパスを指定する必要があります。</p>
+
+<p class="note"><strong>注:</strong> Windows 上に JDK をインストールすると、デフォルトでは「Program Files」ディレクトリにインストールされます。このパス名にはスペースが含まれるために、<code>ant</code> は実行されません。この問題は、JAVA_HOME 変数を次のように指定することで解決できます: <code>set JAVA_HOME=c:\Prora~1\Java\<jdkdir></code> ただし最も簡単な解決策は、JDK をスペースを含まないディレクトリ(例: <code>c:\java\jdk1.6.0_02</code>)にインストールすることです。</p>
+
+
+<h3 id="DebugMode">デバッグ モードでのビルド</h3>
+
+<p>アプリケーションのテストとデバッグをすぐに行いたい場合は、デバッグ モードでアプリケーションをビルドし、すぐにエミュレータにインストールすることができます。デバッグ モードでは、ビルド ツールはデバッグ キーを使用してアプリケーションに自動的に署名します。ただしアプリケーションはリリース モードでテストすることも可能であり、リリース モードでのテストは推奨されています。デバッグ モードは、手動でアプリケーションに署名しなくても、アプリケーションを実行できるようにします。</p>
+
+<p>デバッグ モードでビルドするには:</p>
+
+<ol>
+  <li>コマンドラインを開き、プロジェクトのルート ディレクトリに移動します。</li>
+  <li>Ant を使用してプロジェクトをデバッグ モードでコンパイルします:
+    <pre>ant debug</pre>
+    <p>Android アプリケーションの .apk ファイルがプロジェクトの <code>bin/</code> ディレクトリに、<code><em>&lt;your_DefaultActivity_name&gt;</em>-debug.apk</code> という名前で作成されます。このファイルはデバッグ キーで署名済みです。</p>
+  </li>
+</ol>
+
+<p>ソース ファイルまたはリソースを変更するたびに、アプリケーションの最新バージョンをパッケージングするために、Ant を再度実行する必要があります。</p>
+
+<p>アプリケーションをエミュレータにインストールして実行する方法については、下記の<a href="#Running">アプリケーションの実行</a>セクションをご覧ください。</p>
+
+
+<h3 id="ReleaseMode">リリース モードでのビルド</h3>
+
+<p>アプリケーションをエンドユーザーにリリースして配布する準備ができたら、アプリケーションをリリース モードでビルドする必要があります。リリース モードでビルドした後、最終的な .apk ファイルを使用して追加のテストとデバッグをすることをおすすめします。</p>
+
+<p>リリース モードでビルドするには:</p>
+
+<ol>
+  <li>コマンドラインを開き、プロジェクトのルート ディレクトリに移動します。</li>
+  <li>Ant を使用してプロジェクトをリリース モードでコンパイルします:
+    <pre>ant release</pre>
+    <p>これにより Android アプリケーションの .apk ファイルがプロジェクトの <code>bin/</code> ディレクトリに、<code><em>&lt;your_DefaultActivity_name&gt;</em>.apk</code> という名前で作成されます。</p>
+    <p class="note"><strong>注:</strong> .apk ファイルはこの時点では署名されていません。<em></em>つまり非公開キーで署名するまで、エミュレータや端末にインストールすることはできません。</p>
+  </li>
+</ol>
+
+<p>リリース モードではアプリケーションを署名せずにビルドを行います。このため、アプリケーションをエンドユーザーに配布するためには、次に非公開キーを使用して署名を行う必要があります。この手順を行う方法については、<a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Application</a>をご覧ください。</p>
+
+<p>非公開キーを使用してアプリケーションに署名すると、アプリケーションをエミュレータや端末にインストールできるようになります。これについては次の<a href="#Running">アプリケーションの実行</a>のセクションで説明します。次の方法でウェブ サーバーから端末にインストールすることもできます。署名した APK をウェブサイトにアップロードし、Android ウェブブラウザでその .apk の URL を読み込んでアプリケーションをダウンロードし、インストールを開始します(端末上では、[設定] &gt; [アプリケーション] を選択し、[提供元不明のアプリ] をオンにする必要があります)。<em></em></p>
+
+
+<h2 id="Running">アプリケーションの実行</h2>
+
+<p>端末のハードウェア以外でアプリケーションを実行する場合は、アプリケーションのインストール先となるエミュレータを起動する必要があります。Android エミュレータのインスタンスは、特有の端末構成に合わせて設定された、特定の Android プラットフォームを実行しています。このプラットフォームと構成は、Android 仮想デバイス(AVD)で定義されます。そのためエミュレータを起動する前に、AVD を定義しなくてはいけません。</p>
+
+<p>端末ハードウェアでアプリケーションを実行する場合は、代わりに、<a href="{@docRoot}guide/developing/device.html">端末のでの開発</a> をご覧ください。</p>
+
+<ol>
+  <li><strong>AVD の作成</strong>
+    <ol>
+      <li>コマンドラインを開き、SDK パッケージの <code>tools/</code> ディレクトリに移動します。</li>
+      <li>最初に、「配備ターゲット」を選択する必要があります。選択可能なターゲットを表示するには、次のコマンドを実行します:
+        <pre>android list targets</pre>
+        <p>次のように選択可能な Android ターゲットのリストが表示されます:</p>
+<pre>
+id:1
+    Name: Android 1.1
+    Type: platform
+    API level: 2
+    Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P
+id:2
+    Name: Android 1.5
+    Type: platform
+    API level: 3
+    Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P
+</pre>
+        <p>アプリケーションを実行する Android プラットフォームに一致するターゲットを探します。<code>id</code> の番号を書き留めておき、次のステップで使用します。</p>
+      </li>
+      <li>選択した配備ターゲットを使用して、新しい AVD を作成します:
+        <pre>android create avd --name <em>&lt;your_avd_name&gt;</em> --target <em>&lt;targetID&gt;</em></pre>
+      <li>カスタム ハードウェア プロファイルを作成するかどうかの問い合わせがあります。「yes」と答えると、携帯端末ハードウェアのさまざまな面を定義するための一連の問い合わせがあります(入力を空白のままにすると、かっこ内に表示されたデフォルト値が使用されます)。または、Enter キーを押すと、すべてデフォルト値が使用されます(「no」がデフォルトです)。</li>
+      </li>
+    </ol>
+  </li>
+
+  <li><strong>エミュレータの起動</strong></li>
+    <p>SDK の <code>tools/</code> ディレクトリから、上記で作成した既存の AVD を使用してエミュレータを起動します:
+    <pre>emulator -avd <em>&lt;your_avd_name&gt;</em></pre>
+    <p>エミュレータのインスタンスが起動し、AVD で定義されたターゲットと構成が実行されます。</p>
+  </li>
+  
+  <li><strong>アプリケーションのインストール</strong>
+    <p>SDK の <code>tools/</code> ディレクトリから .apk をエミュレータにインストールします:
+    <pre>adb install <em>/path/to/your/application</em>.apk</pre>
+    <p>複数のエミュレータが実行中の場合、<code>-s</code> オプションでシリアル番号を指定して、アプリケーションをインストールするエミュレーションを指定する必要があります。次に例を示します:</p>
+    <pre>adb -s emulator-5554 install /my/project/path/myapp.apk</pre>
+  </li>
+  <li><strong>アプリケーションを開く</strong>
+    <p>エミュレータで、使用可能なアプリケーションのリストを開き、実行するアプリケーションを探して開きます。</p>
+  </li>
+</ol>
+
+<p>実行するアプリケーションがエミュレータ上にない場合、同じ AVD を指定してエミュレータを再起動してください。Activity を初めてインストールすると、アプリケーション ランチャに表示されず、他のアプリケーションからアクセスできないことがあります。パッケージ マネージャは通常、エミュレータの起動時にしかマニフェストを完全には調べないためです。</p>
+
+<p class="note"><strong>ヒント:</strong> 実行中のエミュレータが 1 つしかない場合、1 つの簡単なステップで、アプリケーションをビルドし、エミュレータにインストールすることができます。プロジェクトのルート ディレクトリに移動し、Ant を使用してインストール モードでプロジェクトをコンパイルします<em></em>(<code>ant install</code>)。これにより、アプリケーションがビルドされ、デバッグ キーにより署名され、現在実行中のエミュレータにインストールされます。現在実行中のエミュレータが複数あると、<code>install</code> コマンドは失敗します。複数のエミュレータからの選択を行うことはできません。</p>
+
+<p>上記で使用したツールについて詳しくは、次のドキュメントをご覧ください:</p>
+<ul>
+  <li><a href="{@docRoot}guide/developing/tools/othertools.html#android">android ツール</a></li>
+  <li><a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a></li>
+  <li><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> (ADB)</li>
+</ul>
+
+
+<h2 id="AttachingADebugger">アプリケーションへのデバッガの接続</h2>
+
+<p>このセクションでは、画面上でのデバッグ情報(CPU の使用率など)の表示方法や、総合開発環境に接続してエミュレータ上で実行するアプリケーションをデバッグする方法について説明します。 </p>
+
+<p>Eclipse プラグインを使用すると、デバッガへの接続は自動化されます。しかし他の総合開発環境でも、デバッグ ポートをリッスンしてデバッグ情報を受信するように設定することができます:</p>
+<ol>
+    <li>総合開発環境とエミュレータ間のポート転送サービスとして機能する <strong><a href="{@docRoot}guide/developing/tools/ddms.html">Dalvik Debug Monitor Server(DDMS)</a>ツールを起動します。</strong></li>
+    <li><strong>エミュレータでオプションのデバッグ構成を設定します</strong>。設定には、デバッガ接続まで Activity のアプリケーション起動をブロックするオプションなどが含まれます。エミュレータでの CPU 使用率や画面の更新率の表示のように、これらのデバッグ用オプションの多くは DDMS がなくても使用できます。</li>
+    <li><strong>総合開発環境を設定して、デバッグ用にポート 8700 に接続します。</strong><a href="{@docRoot}guide/developing/debug-tasks.html#ide-debug-port">総合開発環境を設定してデバッグ ポートに接続する</a> をご覧ください。 </li>
+</ol>
diff --git a/docs/html/intl/ja/guide/index.jd b/docs/html/intl/ja/guide/index.jd
new file mode 100644
index 0000000..73ca18a
--- /dev/null
+++ b/docs/html/intl/ja/guide/index.jd
@@ -0,0 +1,52 @@
+page.title=デベロッパー ガイド
+@jd:body
+
+<p>
+Android デベロッパー ガイドへようこそ。<i></i>デベロッパー ガイドは、Android 向けアプリケーション開発における実用的な入門資料です。この資料では、Android の背後にある概念、アプリケーション構築用のフレームワーク、およびAndroid プラットフォーム向けソフトウェアを開発、テスト、公開するためのツールについて説明します。
+</p>
+
+<p>
+デベロッパー ガイドには Android プラットフォームに関するほとんどのドキュメントが含まれていますが、フレームワーク API に関する参考資料は含まれていません。API の仕様については、上部にある [<a href="{@docRoot}reference/packages.html">リファレンス</a>] タブをご覧ください。
+</p>  
+
+<p>
+左側のパネルに表示されているように、デベロッパー ガイドは複数のセクションに分かれています。各セクションは次のとおりです:
+<p>
+
+<dl>
+<dt><b>Android の基本</b></dt>
+<dd>Android とは何か、基本機能、アプリケーションとの関係など、Android の基本事項について紹介します。</dd>
+
+<dt><b>フレームワーク トピック</b></dt>
+<dd>Android のフレームワークと API の各部分について説明します。フレームワークの概要については、<a href="{@docRoot}guide/topics/fundamentals.html">アプリケーションの基礎</a>を最初にご覧ください。次に、ユーザー インターフェースの設計やリソースの設定、データの保存、権限の利用など、それぞれのトピックを必要に応じて参照してください。</dd>
+
+<dt><b>開発</b></dt>
+<dd>Android の開発とデバッグ用ツールの使用方法、結果のテスト方法について説明します。</dd>
+
+<dt><b>公開</b></dt>
+<dd>アプリケーション配布の準備をする方法と、準備ができたら公開する方法について説明します。</dd>
+
+<dt><b>ベスト プラクティス</b></dt> 
+<dd>効率よく機能し、ユーザーにとって役立つアプリケーションを作成するための推奨テクニックについて説明します。</dd>
+
+<dt><b>チュートリアルとサンプル</b></dt> 
+<dd>Android アプリケーションを構築する方法を例示する段階的なチュートリアルとサンプル コードです。</dd>
+
+<dt><b>付録</b></dt>
+<dd>関連情報、仕様、よくある質問、用語解説などの情報です。</dd>
+</dl>
+
+<p>
+Android 向けプログラム開発の最初のステップは、SDK(ソフトウェア開発キット)をダウンロードすることです。このキットのダウンロード方法と説明については、上部にある [<a href="{@docRoot}sdk/index.html">SDK</a>] タブをご覧ください。
+</p>
+
+<p>
+SDK のダウンロード後は、まずはじめにデベロッパー ガイドを参照してください。コードを実際に見てみることから始めたい場合は、簡単な <a href="{@docRoot}guide/tutorials/hello-world.html">Hello World</a> チュートリアルを参照してください。Android プラットフォーム向けに作成された標準的な「Hello, World」アプリケーションについて説明しています。<a href="{@docRoot}guide/topics/fundamentals.html">アプリケーションの基礎</a>ドキュメントは、アプリケーション フレームワークを理解したいユーザーに最適な出発点となります。
+</p>
+
+
+<p>
+不明点などがある場合は、Android ディスカッション グループへの参加をおすすめします。詳しくは上部にある [<a href="{@docRoot}community/index.html">コミュニティ</a>] タブをご覧ください。
+</p>
+
+<p>デベロッパー ガイドの別のページに移動してから、このページに戻るには、[デベロッパー ガイド] タブをクリックします。 </p>
\ No newline at end of file
diff --git a/docs/html/intl/ja/guide/publishing/app-signing.jd b/docs/html/intl/ja/guide/publishing/app-signing.jd
new file mode 100644
index 0000000..23d8cf7
--- /dev/null
+++ b/docs/html/intl/ja/guide/publishing/app-signing.jd
@@ -0,0 +1,336 @@
+page.title=アプリケーションへの署名
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>署名の概略</h2>
+
+<ul>
+<li>Android アプリケーションはすべて<em>署名する必要がある</em></a></li>
+<li>自己署名キーで署名可能</li>
+<li>アプリケーションの署名方法は重要です。このドキュメントをよくお読みください</li>
+<li>開発プロセスの初期段階で署名戦略を決定します</li>
+</ul>
+
+<h2>このドキュメントの内容</h2>
+
+<ol>
+<li><a href="#overview">概要</a></li>
+<li><a href="#strategies">署名戦略</a></li>
+<li><a href="#setup">署名の基本設定</a></li>
+<li><a href="#debugmode">デバッグ モードでの署名</a></li>
+<li><a href="#releasemode">公開リリースへの署名</a>
+    <ol>
+    <li><a href="#releasecompile">リリース向けのコンパイル</a></li>
+    <li><a href="#cert">適切な秘密鍵の取得</a></li>
+    <li><a href="#signapp">アプリケーションの署名</a></li>
+    <li><a href="#ExportWizard">Eclipse ADT によるコンパイルと署名</a></li>
+    </ol>
+</li>
+<li><a href="#secure-key">秘密鍵のセキュリティ設定</a></li>
+
+</ol>
+
+<h2>関連項目</h2>
+
+<ol>
+<li><a href="{@docRoot}guide/publishing/versioning.html">アプリケーションのバージョニング</a></li>
+<li><a href="{@docRoot}guide/publishing/preparing.html">公開の準備</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>このドキュメントでは、Android アプリケーションを携帯端末ユーザーに公開する前に署名する方法について説明します。</p>
+
+<h2 id="overview">概要</h2>
+
+<p>Android システムでは、インストールするすべてのアプリケーションに対してデジタル署名されて証明書を必要とします。この証明書の秘密鍵は、アプリケーションのデベロッパーが所持するものです。Android システムは証明書をアプリケーションの作成者の識別手段、およびアプリケーション間の信頼関係の確立手段として使用します。証明書は、ユーザーがどのアプリケーションをインストールできるかを制御するものではありません。証明書は認証機関によって署名される必要はありません。通常の Android アプリケーションは自己署名証明書を使用して正常に機能します。</p>
+
+<p>Android アプリケーションの署名について、次の点を理解することが重要です:</p>
+
+<ul>
+  <li>すべてのアプリケーションは<em>署名される必要があります</em>。署名されていないアプリケーションはシステムにインストールされません。</li>
+  <li>アプリケーションの署名に、自己署名証明書を使用できます。認証機関は不要です。</li>
+  <li>アプリケーションをエンド ユーザーにリリースする準備ができたら、適切な秘密鍵を使用してアプリケーションに署名する必要があります。SDK ツールで生成されたデバッグ キーで署名されたアプリケーションは、公開できません。 
+  </li>
+  <li>システムが署名証明書の有効期限を確認するのは、インストール時のみです。アプリケーションのインストール後に署名者証明書が期限切れになった場合、アプリケーションは正常な動作を継続します。</li>
+  <li>標準ツールである Keytool と Jarsigner を使用してキーを生成し、アプリケーションの .apk ファイルに署名できます。</li>
+</ul>
+
+<p>Android システムは、適切に署名されていないアプリケーションをインストールせず、実行もしません。この規則は、実際のデバイスでもエミュレータでも、Android システムが実行されるすべての状況で適用されます。このため、エミュレータまたはデバイス上で実行またはデバッグする前に、アプリケーションの署名を設定する必要があります。</p>
+
+<p>Android SDK ツールは、デバッグ時のアプリケーション署名を支援します。「ADT Plugin for Eclipse」と「Ant ビルド ツール」では両方とも、<em>デバッグ モード</em>と<em>リリース モード</em>の 2 種類の署名モードを利用できます。 
+
+<ul>
+<li>開発およびテスト中は、デバッグ モードでコンパイルできます。デバッグ モードでは、ビルド ツールは JDK に付属の Keytool ユーティリティを使用して、キーストアとキーを既知のエイリアスとパスワードで作成します。コンパイルのたびに、ツールはデバッグ キーを使用してアプリケーションの .apk ファイルに署名します。パスワードは既知のものなので、コンパイルのたびにツールにキーストア/キー パスワードを入力する必要はありません。</li>
+
+<li>アプリケーションをリリースする準備ができたら、リリース モードでコンパイルして、.apk に<span style="color:red">秘密鍵</span>で署名する必要があります。次の 2 通りの方法があります:
+  <ul>
+    <li>Keytool と Jarsigner をコマンド ラインで使用する方法。このアプローチでは、まずアプリケーションを<em>署名されていない</em> .apk にコンパイルします。次に、Jarsigner(または類似のツール)を使用して秘密鍵で .apk に手動で署名します。適切な秘密鍵を所持していない場合は、Keytool を手動で実行して独自のキーストア/キーを生成し、Jarsigner でアプリケーションに署名できます。</li>
+    <li>ADT Export Wizard を使用する方法。ADT プラグイン搭載の Eclipse を使用して開発している場合、Export Wizard を使用してアプリケーションをコンパイルし、秘密鍵を生成して(必要な場合)、.apk に署名できます。この作業をすべて Export Wizard を使用して 1 つのプロセスで実行できます。
+    </li>
+  </ul>
+</li>
+</ul>
+
+<h2 id="strategies">署名戦略</h2>
+
+<p>アプリケーションの署名は、開発アプローチに一部影響します。特に、複数のアプリケーションをリリースする予定の場合、高い影響を与えます。 </p>
+
+<p>一般に、すべてのデベロッパーに推奨される戦略は、アプリケーションの予期される使用期間を通じて同じ証明書ですべてのアプリケーションに署名することです。このようにするには、複数の理由があります: </p>
+
+<ul>
+<li>アプリケーションのアップグレード - アプリケーションのアップグレードをリリースするとき、ユーザーが新バージョンにシームレスにアップグレードできるように、アップグレードされたアプリケーションにも同じ証明書で署名します。システムがアプリケーションのアップデートをインストールする際は、新バージョンの証明書のいずれかが旧バージョンの証明書と一致する場合、システムがアップデートを許可します。一致する証明書を使用せずに署名する場合は、アプリケーションに別のパッケージ名を割り当てる必要があります。この場合、新しいバージョンがまったく新しいアプリケーションとしてインストールされます。 </li>
+
+<li>アプリケーションのモジュール性 - Android システムでは、アプリケーションが要求する場合、同じ証明書で署名されたアプリケーションを同じプロセスで実行できます。これにより、システムはこれらを単一のアプリケーションとして取り扱います。このようにすればアプリケーションをモジュールとして配備でき、ユーザーは必要に応じて各モジュールを個別に更新できます。</li>
+
+<li>許可によるコード/データ共有 - Android システムでは、署名ベースの権限付与を実施しているため、アプリケーションは指定された証明書で署名されている別のアプリケーションに機能を提供できます。同じ証明書で複数のアプリケーションに署名し、署名に基づいた権限のチェックを行うことで、アプリケーションはコードとデータを安全な方法で共有できます。 </li>
+
+</ul>
+
+<p>署名戦略を決定する際のもう 1 つの重要な検討事項として、アプリケーションの署名に使用するキーの有効期間の設定方法があります。</p>
+
+<ul>
+<li>アプリケーションのアップグレードをサポートするには、キーの有効期間は、アプリケーションの予定される試用期間以上である必要があります。有効期間は、25年以上であることが推奨されます。キーの有効期間が切れた場合、ユーザーはアプリケーションの新バージョンにシームレスにアップグレードできなくなります。</li>
+
+<li>同じキーで複数の異なるアプリケーションに署名する場合、キーの有効期間が、今後のアプリケーション スイートに追加される依存アプリケーションを含め、<em>すべてのアプリケーションのすべてのバージョンの</em>予定される使用期間を超えることを確認してください。 </li>
+
+<li>アプリケーションを Android マーケットに公開する予定の場合、アプリケーションの署名に使用するキーの有効期間を、2033 年 10 月 22 日以降の期限に設定する必要があります。マーケット サーバーは、新バージョンが公開されたときにユーザーがマーケット アプリケーションをシームレスにアップグレードできるよう、この要件を義務付けています。 </li>
+</ul>
+
+<p>アプリケーションの設計時にこれらの点を考慮し、アプリケーションの署名に<a href="#cert">適切な証明書</a>を使用してください。 </p>
+
+<h2 id="setup">署名の基本設定</h2>
+
+<p>キーストアとデバッグ キーの生成をサポートするため、SDK ビルド ツールで Keytool を使用できることを初めに確認してください。たいていの場合、「JAVA_HOME」環境変数を設定して適切な JDK を参照させることで、SDK ビルド ツールで Keytool を認識できます。または、JDK バージョンの Keytool を PATH 変数に追加しても認識できます。</p>
+
+<p>Linux バージョンに付属されている GNU Java コンパイラで開発している場合は、gcj バージョンではなく、JDK バージョンの Keytool を使用していることを確認してください。Keytool が既に PATH に指定されている場合は、<code>/usr/bin/keytool</code> の symlink を指していることがあります。この場合は、symlink ターゲットが JDK の Keytool を指していることを確認してください。</p>
+
+<p>アプリケーションを公開する場合は、Jarsigner ツールをコンピュータで使用できるようにする必要があります。Jarsigner と Keytool の両方が JDK によって提供されます。 </p>
+
+<h2 id="debugmode">デバッグ モードでの署名</h2>
+
+<p>Android ビルド ツールにはデバッグ署名モードがあり、アプリケーションの開発とデバッグがスムーズに行えます。また、.apk をエミュレータまたはデバイスにインストールする際の、署名に対する Android システム要件を満たします。デバッグモードでは、SDK ツールは Keytool を呼び出してデバッグ キーストアとキーを作成します。</p>
+
+<p>SDK ツールは事前に指定された名前とパスワードを使用してデバッグ キーストア/キーを作成します。</p>
+<ul>
+<li>キーストア名 – 「debug.keystore」</li>
+<li>キーストアのパスワード – 「android」</li>
+<li>キーのエイリアス – 「androiddebugkey」</li>
+<li>キーのパスワード – 「android」</li>
+<li>CN – 「CN=Android Debug,O=Android,C=US」</li>
+</ul></p>
+
+<p>必要に応じて、デバッグ キーストア/キーの場所および名前を変更できます。また、自分で作成したデバッグ キーストア/キーを指定することもできます。Eclipse/ADT で、[[]<strong>ウィンドウ(Windows)</strong>] &gt; [[]<strong>設定(Prefs)</strong>] &gt; [[]<strong>Android</strong>] &gt; [[]<strong>ビルド(Build)</strong>] を選択します。ただし、自分で作成したデバッグ キーストア/キーは、デフォルトのデバッグ キー(上述)と同じキーストア/キー名とパスワードを使用する必要があります。</p>
+
+<p class="note"><strong>注:</strong> デバッグ証明書で署名した場合は、アプリケーションを<em>公開できません</em>。</p>
+
+<h3>Eclipse ユーザー</h3>
+
+<p>Eclipse/ADT で開発し、Keytool を上記のように設定してある場合は、デバッグモードにおける署名はデフォルトで有効になっています。アプリケーションを実行またはデバッグするときに、ADT は .apk にデバッグ証明書で署名し、エミュレータにインストールします。ADT が Keytool にアクセスできる場合は、ユーザーは特に操作する必要はありません。</p>
+
+<h3>Ant ユーザー</h3>
+
+<p>Ant を使用して .apk ファイルを構築する場合、デバッグ署名モードは <code>debug</code> オプションを使用することで有効になります(<code>android</code> ツールで生成された <code>build.xml</code> ファイルを使用していることが前提となります)。<code>ant debug</code> を実行してアプリケーションをコンパイルする際、ビルド スクリプトはキーストア/キーを生成し、.apk に署名します。ユーザーは操作する必要はありません。詳細は、<a href="{@docRoot}guide/developing/other-ide.html#DebugMode">その他の統合開発環境での開発: デバッグモードにおけるビルド </a> をお読みください。</p>
+
+
+<h3 id="debugexpiry">デバッグ証明書の有効期限</h3>
+
+<p>デバッグ モード(Eclipse/ADT と Ant ビルドのデフォルト)でのアプリケーション署名に使用した自己署名証明書には、作成日から 365 日の有効期限が設定されます。</p>
+
+<p>証明書の期限が切れると、ビルド エラーが発生します。Ant ビルドでは、エラーは次のようになります:</p>
+
+<pre>debug:
+[echo] Packaging bin/samples-debug.apk, and signing it with a debug key...
+[exec] Debug Certificate expired on 8/4/08 3:43 PM</pre>
+
+<p>Eclipse/ADT では、Android コンソールに同様のエラーが表示されます。</p>
+
+<p>この問題を解決するには、<code>debug.keystore</code> ファイルを削除します。AVD のデフォルトの格納場所は、OS X と Linux の場合は <code>~/.android/avd</code>、Windows XP の場合は <code>C:\Documents and Settings\<user>\.android\</code>、Windows Vista の場合は <code>C:\Users\<user>\.android\</code> です。</p>
+
+
+<p>次にビルドを行うと、ビルド ツールは新しいキーストアとデバッグ キーを再度生成します。</p>
+
+<p>開発コンピュータがグレゴリオ暦以外のロケールを使用している場合、ビルド ツールが誤って期限切れのデバッグ証明書を生成することがあります。このため、アプリケーションをコンパイルしようとするとエラーが発生します。解決策については、トラブルシューティング トピックの <a href="{@docRoot}guide/appendix/faq/troubleshooting.html#signingcalendar">ビルド ツールが期限切れのデバッグ証明書を生成するため、アプリケーションがコンパイルできない</a> をご覧ください。 </p>
+
+
+<h2 id="releasemode">公開リリースへの署名</h2>
+
+<p>アプリケーションを他のユーザーに公開する準備ができたら、次のことを行う必要があります:</p>
+<ol>
+  <li>アプリケーションをリリース モードでコンパイルする</li>
+  <li>適切な秘密鍵を取得する</li>
+  <li>アプリケーションに秘密鍵で署名する</li>
+</ol>
+
+<p>以下のセクションでは、これらの手順を実行する方法について説明します。</p>
+
+<p>ADT プラグイン搭載の Eclipse を使用している場合、これらの手順を実行する代わりに Export Wizard を使用して .apk をコンパイルして秘密鍵で署名できます。Export Wizard では、処理過程で新しいキーストアと秘密鍵の生成も可能です。<a href="#ExportWizard">Eclipse ADT によるコンパイルと署名</a>を参考にコンパイルを行ってください。</p>
+
+
+<h3 id="releasecompile">リリース向けのコンパイル</h3>
+
+<p>アプリケーションのリリースを準備するには、リリース モードでコンパイルする必要があります。リリース モードでは、Android ビルド ツールはアプリケーションを通常どおりにコンパイルしますが、デバッグ キーで署名しません。</p>
+
+<p class="warning"><strong>注:</strong> 署名されていないアプリケーション、またはデバッグ キーで署名されたアプリケーションはリリースできません。</p>
+
+<h4>Eclipse ユーザー</h4>
+
+<p><em>署名されていない</em> .apk ファイルを Eclipse からエクスポートするには、パッケージ エクスプローラー(Package Explorer)でプロジェクトを右クリックして、[[]<strong>Android ツール(Android Tools)</strong>] &gt; [[]<strong>署名されていないアプリケーション パッケージのエクスポート(Export Unsigned Application Package)</strong>] を選択します。次に、署名されていない .apk ファイルの場所を指定します(または、<code>AndroidManifest.xml</code> ファイルを Eclipse で開き、[[]<em>概要(Overview)</em>] タブを開いて [[]<strong>署名されていない .apk のエクスポート(Export an unsigned .apk)</strong>] をクリックします)。</p>
+
+<p>Export Wizard では、コンパイルと署名の手順を一緒に処理できます。<a href="#ExportWizard">Eclipse ADT によるコンパイルと署名</a>をご覧ください。</p>
+
+<h4>Ant ユーザー</h4>
+
+<p>Ant を使用している場合は、必要な作業は Ant コマンドでビルド ターゲットとして「release」を指定するだけです。たとえば、Ant を build.xml ファイルがあるディレクトリから実行している場合、コマンドは次のようになります:</p>
+
+<pre>$ ant release</pre>
+
+<p>ビルド スクリプトは、アプリケーション .apk を署名せずにコンパイルします。</p>
+
+
+<h3 id="cert">適切な秘密鍵の取得</h3>
+
+<p>アプリケーションの署名を準備するには、まず署名に使用する適切な秘密鍵があることを確認することが必要です。適切な秘密鍵とは、次の条件を満たすものです:</p>
+
+<ul>
+<li>自分が所有している。</li>
+<li>アプリケーションで識別される、個人、法人、または組織の実体を表す。</li>
+<li>アプリケーションまたはアプリケーション スイートの予期される使用期間を超える有効期間を持っている。有効期間として、25 年以上を推奨します。 
+<p>アプリケーションを Android マーケットに公開する予定の場合、2033 年 10 月 22 日までの有効期間が必要です。有効期間がこの日付以前に期限切れになるキーで署名されたアプリケーションは、アップロードできません。 
+</p></li>
+<li>Android SDK ツールで生成されたデバッグ キーではない。 </li>
+</ul>
+
+<p>自己署名されたキーを使用できます。適切なキーがない場合、Keytool を使用して生成する必要があります。<a href="#setup">基本設定</a>で説明した手順に従って、Keytool を使用できるようにしてください。</p>
+
+<p>Keytool で自己署名キーを生成するには、<code>keytool</code> コマンドを使用して以下に示すオプション(および、必要に応じてその他のオプション)を渡します。 </p>
+
+<p class="warning"><strong>注:</strong> Keytool を実行する前に、<a href="#secure-key">秘密鍵のセキュリティ設定</a>を読んで、キーのセキュリティを確保する方法と、自分とユーザーにとってセキュリティ確保が重要な理由を理解してください。特に、自分のキーを生成する場合、キーストアとキーの両方に強力なパスワードを選択する必要があります。</p>
+
+<table>
+<tr>
+<th>Keytool のオプション</th>
+<th>説明</th>
+</tr>
+<tr>
+<td><code>-genkey</code></td><td>キー ペアを生成します(公開キーと秘密鍵)。</td>
+</tr>
+<tr>
+<td><code>-v</code></td><td>詳しいメッセージを出力する。</td>
+</tr>
+<tr>
+<td><code>-keystore&nbsp;&lt;keystore-name&gt;.keystore</code></td><td>秘密鍵を含むキーストアの名前。</td>
+</tr>
+<tr>
+<td><code>-storepass &lt;password&gt;</code></td><td><p>キーストアのパスワード。</p><p>セキュリティ上の注意として、安全なコンピュータで作業している場合を除き、このオプションをコマンド ラインに指定しないでください。指定しなかった場合、Keytool からパスワードの入力が求められます。このため、パスワードはシェルの履歴に記録されません。</p></td>
+</tr>
+<tr>
+<td><code>-alias &lt;alias_name&gt;</code></td><td>キーのエイリアス。</td>
+</tr>
+<tr>
+<td><code>-keyalg &lt;alg&gt;</code></td><td>キーの生成時に使用する暗号化アルゴリズム。DSA と RSA の 2 つをサポートしています。</td>
+</tr>
+<tr>
+<td><code>-dname &lt;name&gt;</code></td><td><p>キーの作成者を識別する、識別名。値は、自己署名証明書の発行者およびサブジェクト フィールドとして使用されます。 </p><p>このオプションはコマンド ラインで指定する必要はありません。指定しなかった場合、Jarsigner からそれぞれの識別名フィールド(CN、OU など)の入力が求められます。</p></td>
+</tr>
+<tr>
+<td><code>-validity &lt;valdays&gt;</code></td><td><p>キーの有効期間(日数)。 </p><p><strong>注:</strong> 10000 以上の値を推奨します。</p></td>
+</tr>
+<tr>
+<td><code>-keypass &lt;password&gt;</code></td><td><p>キーのパスワード。</p>
+<p>セキュリティ上の注意として、安全なコンピュータで作業している場合を除き、このオプションをコマンド ラインに指定しないでください。指定しなかった場合、Keytool からパスワードの入力が求められます。このため、パスワードはシェルの履歴に記録されません。</p></td>
+</tr>
+</table>
+
+
+<p>秘密鍵を生成する Keytool コマンドの例を示します。</p>
+
+<pre>$ keytool -genkey -v -keystore my-release-key.keystore 
+-alias alias_name -keyalg RSA -validity 10000</pre>
+
+<p>上記のコマンド例を実行すると、Keytool からキーストアとキーのパスワードと、キーの識別名フィールドの指定が求められます。キーストアが <code>my-release-key.keystore</code> というファイルとして生成されます。キーストアとキーは、入力したパスワードで保護されます。キーストアには 1 つのキーが含まれ、10000 日間有効です。エイリアスは、後で使用する名前で、アプリケーションに署名するときにこのキーストアを参照する名前です。 </p>
+
+<p>Keytool の詳細は <a
+href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security">http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security</a> のドキュメント(英語のみ)をご覧ください。</p>
+
+
+<h3 id="signapp">アプリケーションの署名</h3>
+
+<p>リリースする .apk に実際に署名する準備ができたら、Jarsigner ツールを使用して署名できます。<a href="#setup">基本設定</a>で説明したように、Jarsigner をコンピュータで使用できることを確認してください。また、秘密鍵を含むキーストアがあることも確認してください。</p>
+
+<p>アプリケーションに署名するには、Jarsigner を実行して、アプリケーションの .apk と、.apk の署名に使用する秘密鍵を含むキーストアの両方を参照します。以下の表では、使用できるオプションを示します。 <p>
+
+<table>
+<tr>
+<th>Jarsigner のオプション</th>
+<th>説明</th>
+</tr>
+<tr>
+<td><code>-keystore&nbsp;&lt;keystore-name&gt;.keystore</code></td><td>秘密鍵を含むキーストアの名前。</td>
+</tr>
+<tr>
+<td><code>-verbose</code></td><td>詳しいメッセージを出力する。</td>
+</tr>
+<tr>
+<td><code>-storepass &lt;password&gt;</code></td><td><p>キーストアのパスワード。 </p><p>セキュリティ上の注意として、安全なコンピュータで作業している場合を除き、このオプションをコマンド ラインに指定しないでください。指定しなかった場合、Jarsigner からパスワードの入力が求められます。このため、パスワードはシェルの履歴に記録されません。</p></td>
+</tr>
+<tr>
+<td><code>-keypass &lt;password&gt;</code></td><td><p>秘密鍵のパスワード。 </p><p>セキュリティ上の注意として、安全なコンピュータで作業している場合を除き、このオプションをコマンド ラインに指定しないでください。指定しなかった場合、Jarsigner からパスワードの入力が求められます。このため、パスワードはシェルの履歴に記録されません。</p></td>
+</tr>
+</table>
+
+<p>Jarsigner を使用して <code>my_application.apk</code> というアプリケーション パッケージに署名する例を、上記で作成したキーストアを使用して示します。 
+</p>
+
+<pre>$ jarsigner -verbose -keystore my-release-key.keystore 
+my_application.apk alias_name</pre>
+
+<p>上記のコマンドを実行すると、Jarsigner からキーストアとキーのパスワードの入力が求められます。.apk がその場で変更され、.apk は署名されます。.apk に別のキーで複数回署名できます。</p>
+
+<p>.apk が署名されたことを確認するには、次のようなコマンドを使用できます:</p>
+
+<pre>$ jarsigner -verify my_signed.apk</pre>
+
+<p>.apk が適切に署名されると、Jarsigner から「jar verified」と出力されます。詳細情報が必要な場合は、次のコマンドを使用できます。</p>
+
+<pre>$ jarsigner -verify -verbose my_application.apk</pre>
+
+<p>または、次のコマンドを使用します。</p>
+
+<pre>$ jarsigner -verify -verbose -certs my_application.apk</pre>
+
+<p>上記の <code>-certs</code> オプションが付加されたコマンドでは、「CN=」行が出力され、キーの作成者が示されます。</p>
+
+<p class="note"><strong>注:</strong> 「CN=Android Debug」と出力される場合、.apk が Android SDK によって生成されたデバッグ キーで署名されたことを示しています。アプリケーションをリリースする予定の場合は、デバッグ キーではなく秘密鍵で署名する必要があります。</p>
+
+<p>Jarsigner の詳細は <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security">http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security</a> のドキュメント(英語のみ)をご覧ください。</p>
+
+
+<h3 id="ExportWizard">Eclipse ADT によるコンパイルと署名</h3>
+
+<p>ADT 搭載 Eclipse を使用している場合、Export Wizard を使用して<em>署名済み</em> .apk をエクスポートできます(必要に応じて、新しいキーストアを作成することもできます)。Export Wizard は、Keytool と Jarsigner のすべての処理を、コマンド ラインを使用せず、グラフィカル ユーザー インターフェースで署名を実行できます。Export Wizard は Keytool と Jarsigner の両方を使用するため、上記の<a href=#setup">署名の基本設定</a>の条件を満たすコンピュータで使用できます。</p>
+
+<p>署名された .apk を作成するには、パッケージ エクスプローラー(Package Explorer)でプロジェクトを右クリックして、<strong>[[]Android ツール(Android Tools)] &gt; [[]署名済みアプリケーション パッケージのエクスポート(Export Signed Application Package)]</strong> を選択します(または、<code>AndroidManifest.xml</code> ファイルを Eclipse で開き、[[]<em>概要(Overview)</em>] タブを開いて [[]<strong>Export Wizard を使用する(Use the Export Wizard)</strong>] をクリックします)。表示されたウィンドウには、アプリケーションのエクスポート中に見つかったエラーが表示されます。エラーが見つからなかった場合は Export Wizard で処理を続行します。.apk に署名する秘密鍵の選択や、新しいキーストアと秘密鍵の作成など、アプリケーション署名のプロセスを手順を追って実行できます。</p>
+
+<p>Export Wizard が完了すると、配布可能な署名済み .apk が作成されています。</p>
+
+
+<h2 id="secure-key">秘密鍵のセキュリティ設定</h2>
+
+<p>秘密鍵のセキュリティ設定は、作成者とユーザーの両者にとって重要です。他人にキーを使用させたり、第三者が見つけて使用できるような安全ではない場所にキーストアとキーを放置したりすると、作成者とユーザー間の信頼が損なわれます。 </p>
+
+<p>他者が許可を得ずにキーを取得した場合、その人物はアプリケーションに署名して配布し、本物のアプリケーションを故意に置き換えたり破損させたりすることができます。このような人物は、身元を詐称してアプリケーションに署名して配布し、その他のアプリケーションまたはシステム自体を攻撃したり、ユーザー データを破損させたり盗み出したりすることもあります。 </p>
+
+<p>キーの有効期限が切れるまで、秘密鍵のセキュリティを常に適切に維持できるかは、デベロッパーとしての評価を左右します。キーを安全に保つためのヒントをいくつか紹介します。 </p>
+
+<ul>
+<li>キーストアとキーに強力なパスワードを選択します。</li>
+<li>Keytool でキーを生成するとき、<em></em>コマンド ラインで <code>-storepass</code> および <code>-keypass</code> オプションを指定しないようにします。指定すると、パスワードがシェル履歴に記録され、コンピュータのすべてのユーザーがアクセスできるようになります。</li>
+<li>同様に、Jarsigner でアプリケーションに署名するとき、<em></em>コマンド ラインで <code>-storepass</code> と <code>-keypass</code> オプションを指定しないようにします。 </li>
+<li>秘密鍵を誰にも与えたり貸したりせず、不正なユーザーにキーストアとキーのパスワードを知られないようにします。</li>
+</ul>
+
+<p>一般的には、キーの生成、使用、保管に関して常識的な注意を払っていれば、セキュリティを確保することができます。 </p>
\ No newline at end of file
diff --git a/docs/html/intl/ja/guide/publishing/preparing.jd b/docs/html/intl/ja/guide/publishing/preparing.jd
new file mode 100644
index 0000000..f1e7b45
--- /dev/null
+++ b/docs/html/intl/ja/guide/publishing/preparing.jd
@@ -0,0 +1,154 @@
+page.title=公開の準備
+@jd:body
+
+<!--
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+
+<ol>
+<li><a href=""></a></li>
+</ol>
+
+</div>
+</div>
+-->
+
+<p>アプリケーションの公開とは、アプリケーションをテストして適切にパッケージし、Android 搭載の携帯端末のユーザーが利用できる状態にすることです。</p>
+
+<p>アプリケーションを公開して Android 搭載デバイスにインストールするには、いくつかの作業を行ってアプリケーションの準備を整える必要があります。このドキュメントでは、アプリケーションのリリースを成功させるための準備における、重要なチェックポイントを説明しています。
+</p>
+
+<p>アプリケーションを Android マーケットに公開する場合は、アプリケーションの具体的な準備要件について <a
+href="{@docRoot}guide/publishing/publishing.html#market">Android マーケットでの公開</a> もご覧ください。 </p>
+
+<p>アプリケーションを公開する方法の一般的な情報については、<a href="{@docRoot}guide/publishing/publishing.html">Publishing Your Applications</a> のドキュメントをご覧ください。 </p>
+
+<div class="special">
+
+<p>アプリケーションのリリースを準備する前の作業:</p>
+
+<ol>
+<li>アプリケーションを実際のデバイスで徹底的にテストする </li>
+<li>アプリケーションへのエンド ユーザー ライセンス契約の追加を検討する</li>
+<li>アプリケーションのマニフェストにアイコンとラベルを指定する</li>
+<li>ロギングとデバッグを無効にして、データとファイルをクリーンアップする</li>
+</ol>
+
+<p>アプリケーションの最終コンパイルを実行する前の作業:</p>
+
+<ol start="5">
+<li>アプリケーションでバージョン管理を行う</li>
+<li>適切な暗号化キーを取得する</li>
+<li>アプリケーションが MapView 要素を使用している場合は、Maps API キーに登録する</li>
+</ol>
+
+<p><em>アプリケーションのコンパイル</em></p>
+<p>アプリケーションをコンパイルした後の作業:</p>
+<ol start="8">
+<li>アプリケーションに署名する</li>
+<li>コンパイルしたアプリケーションをテストする</li>
+</ol>
+</div>
+
+<h2 id="releaseready">アプリケーションのリリースを準備する前の作業</h2>
+
+<h3 id="test">1. アプリケーションを実際のデバイスで徹底的にテストする</h3>
+
+<p>アプリケーションをできる限り広範に徹底的にテストすることが重要です。この作業を支援するため、Android では多数のテスト用クラスとツールを用意しています。{@link android.app.Instrumentation Instrumentation} を使用して JUnit およびその他のテスト ケースを実行できます。また、<a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a> などのテスティング ツールを使用できます。  </p>
+
+<ul>
+<li>ユーザーがアプリケーションを正常に実行できるようにするため、アプリケーションが実行されると予想されるタイプの携帯端末の実機を入手してください。実際のデバイスで、実際のネットワーク条件の下でアプリケーションをテストします。アプリケーションを実際のデバイスでテストすることは非常に重要です。これによって、作成したユーザー インターフェース要素のサイズが正しく(特にタッチスクリーン UI の場合)、アプリケーションのパフォーマンスと電池効率が適正であることを確認できるからです。</li>
+
+<li>アプリケーションの対象とするタイプの携帯端末が手に入らない場合は、<code>-dpi</code>、<code>-device</code>、<code>-scale</code>、<code>-netspeed</code>、<code>-netdelay</code>、<code>-cpu-delay</code> などのエミュレータ オプションを使用して、エミュレータの画面、ネットワーク パフォーマンス、その他の属性をモデル化して可能な限り対象デバイスに適応させることができます。このようにして、アプリケーションの UI とパフォーマンスをテストできます。ただし、公開する前にアプリケーションを実際の対象デバイスでテストすることを強く推奨します。 </li>
+
+<li>アプリケーションが <a href="http://www.t-mobileg1.com/">T-Mobile G1</a> デバイスを対象としている場合、UI が画面の向き変更に対応しているか確認してください。 </li>
+</ul>
+
+<h3 id="eula">2. アプリケーションへのエンドユーザー ライセンス契約の追加を検討する</h3>
+
+<p>個人、組織、知的財産を保護するため、アプリケーションのエンドユーザー ライセンス契約(EULA)を付加することを推奨します。 
+
+<h3 id="iconlabel">3. アプリケーションのマニフェストにアイコンとラベルを指定する</h3>
+
+<p>アプリケーションのマニフェストに指定するアイコンとラベルは、アプリケーションのアイコンと名前としてユーザーに表示されるため、重要な要素です。アイコンとラベルは、デバイスの [[]ホーム] 画面や、[[]アプリケーションの管理]、[[]マイダウンロード] などに表示されます。また、公開サービスによってアイコンとラベルがユーザーに表示される可能性もあります。 </p>
+
+<p>アイコンとラベルを指定するには、<code>android:icon</code> と <code>android:label</code> 属性をマニフェストの <code>&lt;application&gt;</code> 要素に定義します。 </p>
+
+<p>アイコンのデザインについては、組み込みの Android アプリケーションのスタイルとできるだけ統一感を持たせてください。</p>
+
+<h3 id="logging">4. ロギングとデバッグを無効にして、データとファイルをクリーンアップする</h3>
+
+<p>リリース時にはデバッグ機能を無効にし、デバッグおよびその他の不要なデータ/ファイルをアプリケーション プロジェクトから削除してください。</p>
+<ul>
+<li><code>android:debuggable="true"</code> 属性をマニフェストの <code>&lt;application&gt;</code> 要素から削除します。</li>
+<li>ログ ファイル、バックアップ ファイル、およびその他の不要なファイルをアプリケーション プロジェクトから削除します。</li>
+<li>個人的または自分専用のデータがないか確認し、必要に応じて削除します。</li>
+<li>ソース コード内に {@link android.util.Log} メソッドへの呼び出しがある場合は、無効にします。</li>
+</ul>
+
+<h2 id="finalcompile">アプリケーションの最終コンパイルを実行する前の作業</h2>
+
+<h3 id="versionapp">5. アプリケーションでバージョン管理を行う</h3>
+
+<p>アプリケーションをコンパイルする前に、アプリケーションにバージョン番号を定義しておく必要があります。定義するには、アプリケーションのマニフェスト ファイルの <code>&lt;manifest&gt;</code> 要素の <code>android:versionCode</code> と <code>android:versionName</code> 属性の両方に適切な値を指定します。バージョン番号の設定は、全体的なアプリケーションアップグレードの計画を考慮して、慎重に検討してください。 </p>
+
+<p>これまでにリリースしたバージョンがある場合、最新のアプリケーションのバージョン番号を旧バージョンから増加させる必要があります。アプリケーションのマニフェスト ファイルの <code>&lt;manifest&gt;</code> 要素の <code>android:versionCode</code> と <code>android:versionName</code> 属性の両方を適切な値を使用して増加する必要があります。 </p>
+
+<p>アプリケーションのバージョン情報を定義する方法は、<a href="{@docRoot}guide/publishing/versioning.html">Versioning Your Applications</a>をご覧ください。</p>
+
+<h3 id="cryptokey">6. 適切な暗号化キーを取得する</h3>
+
+<p>ここまで準備作業をすべて読んで実行していれば、アプリケーションはコンパイルされ、署名の準備ができています。.apk の内部では、アプリケーションは適切にバージョン管理されており、上記のように余分なファイルや非公開データは削除されています。 </p>
+
+<p>アプリケーションに署名する前に、適切な非公開キーがあることを確認する必要があります。非公開キーを取得(または生成)する方法については、<a href="{@docRoot}guide/publishing/app-signing.html#cert">適切な非公開キーの取得</a>をご覧ください。</p>
+
+<p>適切な非公開キーを取得(または生成)したら、キーを使用して次の手順を実行します:</p>
+
+<ul>
+<li>アプリケーションが MapView 要素を使用している場合は、Maps API キー(以下をご覧ください)に登録します。</li>
+<li>以降の準備プロセスで、リリースするアプリケーションに署名します。</li>
+</ul>
+
+<h3 id="mapsApiKey">7. アプリケーションが MapView 要素を使用している場合は、Maps API キーに登録する</h3>
+
+<div class="sidebox" style="margin-bottom:.5em;padding:1em;"><p>
+Maps API キーを取得する方法は、<a
+href="http://code.google.com/android/add-ons/google-apis/mapkey.html">Maps API キーの取得(英語のみ)</a> をご覧ください。</p></div>
+
+<p>アプリケーションが Mapview 要素を使用する場合、アプリケーションを Google Maps サービスで登録し、Maps API キーを取得する必要があります。その後、MapView で Google Maps からデータを取得できるようになります。この処理を行うため、Maps サービスに署名証明書の MD5 フィンガープリントを提出します。 </p>
+
+<p>開発中は、SDK ツールが生成したデバッグ キーを登録して一時的な Maps API キーを取得できます。ただし、アプリケーションを公開する前には、非公開キーに基づく新しい Maps API キーで登録する必要があります。 </p>
+
+<p>アプリケーションが MapView 要素を使用する場合、次の点を理解することが重要です:</p>
+
+<ol>
+<li>アプリケーションをリリース用にコンパイルする前に、Maps API キーを取得する必要があります。<em></em>このキーを、アプリケーションのレイアウト ファイルにある各 MapView 要素の、<code>android:apiKey</code> という特殊な属性に追加する必要があるからです。MapView オブジェクトをコードから直接インスタンス化している場合は、Maps API キーをコンストラクタのパラメータとして渡す必要があります。
+</li>
+<li>アプリケーションの MapView 要素が参照する Maps API キーは Google Maps 内で登録され、アプリケーションの署名に使用される証明書に登録される必要があります。これはアプリケーションを公開する際に特に重要です。MapView 要素は、アプリケーションの署名に使用されるリリース証明書に登録されるキーを参照する必要があります。  </li>
+<li>SDK ツールが生成したデバッグ証明書を登録して一時的な Maps API キーを取得している場合、リリース証明書を登録して新しい Maps API キーを取得する<em>必要があります</em>。また、MapView 要素を変更して、デバッグ証明書と関連付けられたキーではなく、新しいキーを参照させることも忘れないでください。このようにしないと、MapView 要素には Maps データをダウンロードする許可が与えられません。 </li>
+<li>アプリケーションの署名に使用する非公開キーを変更するには、Google Maps サービスから新しい Maps API キーを取得する<em>必要があります</em>。新しい Maps API キーを取得してすべての MapView 要素に適用してください。以前のキーを参照する MapView 要素には、Maps データをダウンロードする許可が与えられません。 </li>
+</ol>
+
+<p>署名と非公開キーについては、<a
+href="{@docRoot}guide/publishing/app-signing.html">アプリケーションへの署名</a>をご覧ください。</p>
+
+
+<h2 id="compile">アプリケーションのコンパイル</h2>
+
+<p>前述のセクションで説明したアプリケーションの準備ができたら、アプリケーションをリリース用にコンパイルできます。 </p>
+
+<h2 id="post-compile">アプリケーションをコンパイルした後の作業</h2>
+
+<h3 id="signapp">8. アプリケーションに署名する</h3>
+
+<p>非公開キーを使用してアプリケーションに署名します。アプリケーションに正しく署名することは、非常に重要です。詳細は、<a href="{@docRoot}guide/publishing/app-signing.html">アプリケーションへの署名</a>をご覧ください。 </p>
+
+<h3 id="testapp">9. コンパイルして署名したアプリケーションのテスト</h3>
+
+<p>コンパイルしたアプリケーションをリリースする前に、対象とする携帯端末(および可能ならば対象ネットワーク)上で徹底的にテストする必要があります。特に、UI 部分の MapView 要素がマップ データを正常に受信していることを確認してください。正常に受信していない場合、<a href="#mapsApiKey">Maps API キーに登録する</a>に戻って問題を解決してください。アプリケーションがサーバー側サービスを正しく利用できること、指定データまたは使用データを正しく処理できること、そして認証要件を正常に処理できることも確認してください。  </p>
+
+<p>これらのテストが完了したら、アプリケーションを携帯端末ユーザーに公開する準備が整ったと言えるでしょう。</p>
+
+
diff --git a/docs/html/intl/ja/guide/publishing/versioning.jd b/docs/html/intl/ja/guide/publishing/versioning.jd
new file mode 100644
index 0000000..bf86016
--- /dev/null
+++ b/docs/html/intl/ja/guide/publishing/versioning.jd
@@ -0,0 +1,100 @@
+page.title=アプリケーションのバージョニング
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>バージョン管理の概略</h2>
+
+<ul>
+<li>アプリケーションにはバージョンを設定する必要がある<em></em></a></li>
+<li>バージョンは、アプリケーションのマニフェスト ファイルで設定する</li>
+<li>アプリケーションのバージョン管理方法は、ユーザーのアップグレード方法に影響 </li>
+<li>開発プロセスの初期段階で、今後のリリースの検討事項を含めて、バージョン管理戦略を決定します</li>
+</ul>
+
+<h2>このドキュメントの内容</h2>
+
+<ol>
+<li><a href="#appversion">アプリケーションのバージョンの設定</a></li>
+<li><a href="#minsdkversion">最小システム API バージョンの指定</a>
+</ol>
+
+
+<h2>関連項目</h2>
+
+<ol>
+<li><a href="{@docRoot}guide/publishing/preparing.html">公開の準備</a></li>
+<li><a href="{@docRoot}guide/publishing/publishing.html#market">Android マーケットでの公開</a></li>
+<li><a href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>バージョン管理のコンポーネントは、アプリケーションのアップグレード及びメンテナンスの計画を立てるのに重要です。 </p>
+
+<ul>
+<li>ユーザーは、デバイスにインストールされたアプリケーション バージョンと、インストールが可能なアップグレード バージョンについて、特定の情報が必要です。 </li>
+<li>スイートとして公開されたその他のアプリケーションなどでは、アプリケーションのバージョンをシステムに問い合わせて、互換性と依存関係を確認する必要があります。</li>
+<li>アプリケーションを公開するサービスでは、アプリケーションにバージョンを問い合わせて、バージョンをユーザーに表示できるようにする必要があります。公開サービスでは、互換性を確認してアップグレードとダウングレードの関係を確立するために、アプリケーション バージョンを確認する必要があります。</li>
+</ul>
+
+<p>Android システム自体は、アップグレードや互換性の制約の実施などのために、アプリケーション バージョン情報をアプリケーションに対して<em>確認することはありません</em>。代わりに、アプリケーションにおけるバージョン制約はユーザーまたはアプリケーション自体によって完全に実施されます。 </p>
+
+<p>Android システムが確認を行うのは、アプリケーションによってマニフェストの <code>minSdkVersion</code> 属性に指定されたシステム バージョン互換性です。<em></em>この属性によりアプリケーションは互換性を持つ最小システム API を指定できます。詳細は、<a href="#minsdkversion">最小システム API バージョンの指定</a>をご覧ください。
+
+<h2 id="appversioning">アプリケーションのバージョンの設定</h2>
+<p>アプリケーションのバージョン情報を定義するには、アプリケーションのマニフェスト ファイルで属性を設定します。2 つの属性を使用でき、常にこの両方に値を定義することが推奨されています: </p>
+
+<ul>
+<li><code>android:versionCode</code> - アプリケーション コードのバージョンを他のバージョンと相対的に示す整数値。 
+
+<p>この値は整数なので、その他のアプリケーションはプログラムでバージョンの値を評価して関係を確認できます(たとえば、このバージョンがアップグレードかダウングレードなのか、など)。任意の整数値を設定できますが、アプリケーションの後続のリリースでは、現在より大きな値を使用するようにしてください。システムではこのバージョン管理の基準を強制しませんが、後継リリースの値を増加させることは標準的です。 </p>
+
+<p>通常、アプリケーションの最初のバージョンの versionCode を 1 に設定してリリースし、その後は各リリースについて、リリースがメジャー リリースであってもマイナー リリースであっても、値を単調増加させます。これは、<code>android:versionCode</code> の値は、ユーザーに表示されるアプリケーション リリース バージョンと類似している必要性はないことを意味します。以下の <code>android:versionName</code> をご覧ください。アプリケーションと公開サービスでは、このバージョンの値はユーザーには表示されません。</p>
+</li>
+<li><code>android:versionName</code> - アプリケーション コードのリリース バージョンを表す文字列値で、ユーザーに表示される値です。 
+<p>値は文字列なので、アプリケーション バージョンを「&lt;major&gt;.&lt;minor&gt;.&lt;point&gt;」といった文字列や、その他のタイプの絶対的または相対的バージョン ID として記述できます。 </p>
+
+<p><code>android:versionCode</code> の場合と同様に、システムではこの値をアプリケーションでユーザーに表示する以外の目的で内部的に利用することはありません。公開サービスでは、ユーザーに表示するために <code>android:versionName</code> 値を取り出す可能性もあります。</p>
+</li>
+</ul>
+
+<p>これらのバージョン属性の両方をマニフェスト ファイルの <code>&lt;manifest&gt;</code> 要素で定義します。 </p>
+
+<p>ここに、<code>&lt;manifest&gt;</code> 要素の <code>android:versionCode</code> と <code>android:versionName</code> 属性を示すマニフェストの例を示します。 </p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.example.package.name"
+      android:versionCode="2"
+      android:versionName="1.1"&gt;
+    &lt;application android:icon="@drawable/icon" android:label="@string/app_name"&gt;
+        ...
+    &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+<p>この例では、<code>android:versionCode</code> 値は現在の .apk がこのアプリケーション コードの 2 番目のリリースを含んでいることを表し、これは <code>android:codeName</code> 文字列が示すようにマイナー後継リリースであることを示します。 </p>
+
+<p>Android フレームワークには、アプリケーションがシステムに別のアプリケーションのバージョン情報を問い合わせる API が用意されています。バージョン情報を取得するため、アプリケーションは {@link android.content.pm.PackageManager#getPackageInfo(java.lang.String, int)} 
+method of {@link android.content.pm.PackageManager PackageManager}. </p> を使用します。
+
+<h2 id="minsdkversion">最小システム API バージョンの指定</h2>
+
+<p>アプリケーションが最低でも Android プラットフォームの特定のバージョンを必要とする場合、このバージョンを API レベルの ID としてアプリケーションのマニフェスト ファイルに指定できます。このようにすると、互換性のあるバージョンの Android システムを実行しているデバイスにのみアプリケーションをインストールできるようになります。 </p>
+
+<p>最小システム バージョンをマニフェストに指定するには、次の属性を使用します: </p>
+
+<ul>
+<li><code>android:minSdkVersion</code> - Android プラットフォームのコード バージョンに対応する整数値。 
+<p>アプリケーションのインストールを準備する際に、システムはこの属性の値を確認して、システム バージョンと比較します。<code>android:minSdkVersion</code> 値がシステム バージョンよりも大きい場合、システムはアプリケーションのインストールを中止します。 </p>
+
+<p>この属性をマニフェストに指定しない場合、システムではアプリケーションがすべてのプラットフォーム バージョンと互換性があると仮定します。</p></li>
+</ul>
+
+<p>アプリケーションに最小プラットフォーム バージョンを指定するには、<code>&lt;uses-sdk&gt;</code> 要素を <code>&lt;manifest&gt;</code> の子として追加し、<code>android:minSdkVersion</code> を属性として定義します。 </p>
+
+<p>詳細は、<a href="{@docRoot}sdk/android-1.1.html">Android System Image 1.1 Version Notes</a> もご覧ください。</p>
diff --git a/docs/html/intl/ja/guide/topics/fundamentals.jd b/docs/html/intl/ja/guide/topics/fundamentals.jd
new file mode 100644
index 0000000..247d076
--- /dev/null
+++ b/docs/html/intl/ja/guide/topics/fundamentals.jd
@@ -0,0 +1,922 @@
+page.title=開発の基礎
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>主なクラス</h2>
+<ol>
+<li>{@link android.app.Activity}</li>
+<li>{@link android.app.Service}</li>
+<li>{@link android.content.BroadcastReceiver}</li>
+<li>{@link android.content.ContentProvider}</li>
+<li>{@link android.content.Intent}</li>
+</ol>
+
+<h2>このドキュメントの内容</h2>
+<ol>
+<li><a href="#appcomp">アプリケーションのコンポーネント</a>
+  <ol>
+    <li><a href="#actcomp">コンポーネントのアクティブ化: インテント</a></li>
+    <li><a href="#endcomp">コンポーネントの終了</a></li>
+    <li><a href="#manfile">マニフェスト ファイル</a></li>
+    <li><a href="#ifilters">インテント フィルタ</a></li>
+  </ol></li>
+<li><a href="#acttask">アクティビティとタスク</a>
+  <ol>
+    <li><a href="#afftask">親和性と新しいタスク</a></li>
+    <li><a href="#lmodes">起動モード</a></li>
+    <li><a href="#clearstack">スタックのクリア</a></li>
+    <li><a href="#starttask">タスクの開始</a></li>
+  </ol></li>
+<li><a href="#procthread">プロセスとスレッド</a>
+  <ol>
+    <li><a href="#procs">プロセス</a></li>
+    <li><a href="#threads">スレッド</a></li>
+    <li><a href="#rpc">リモート プロシージャ コール</a></li>
+    <li><a href="#tsafe">スレッドセーフなメソッド</a></li>
+  </ol></li>
+<li><a href="#lcycles">コンポーネントのライフサイクル</a>
+  <ol>
+    <li><a href="#actlife">アクティビティのライフサイクル</a></li>
+    <li><a href="#servlife">サービスのライフサイクル</a></li>
+    <li><a href="#broadlife">ブロードキャスト レシーバのライフサイクル</a></li>
+    <li><a href="#proclife">プロセスとライフサイクル</a></li>
+  </ol></li>
+</ol>
+</div>
+</div>
+
+<p>
+Android アプリケーションはすべて Java プログラミング言語で記述します。コンパイル済みの Java コード(およびそのアプリケーションに必要なすべてのデータやリソース ファイル)は、<a href="{@docRoot}guide/developing/tools/aapt.html"><code>aapt</code> ツール</a>を使用して Android パッケージにバンドルします。Android パッケージは、拡張子が {@code .apk} のアーカイブ ファイルです。<i></i>ユーザーは、このファイルをデバイスにダウンロードして利用します。つまり、Android パッケージは、アプリケーションをモバイル デバイスに配布およびインストールするための媒体として機能します。1 つの {@code .apk} ファイルに含まれているすべてのコードが、1 つのアプリケーションと見なされます。<i></i>
+</p>
+
+<p>
+各 Android アプリケーションは、以下に示すさまざまな方法で他のアプリケーションから隔離されています:
+</p>
+
+<ul>
+<li>すべてのアプリケーションは、デフォルトではそのアプリケーション個別の Linux プロセスで実行されます。Android は、アプリケーション コードの実行が必要になったときにプロセスを開始し、その必要がなくなって他のアプリケーションからシステム リソースを要求されたときにプロセスを終了します。</li>
+
+<li>プロセスごとに専用の Java 仮想マシン(VM)が割り当てられるため、アプリケーション コードは他のアプリケーションから隔離された状態で実行されます。</li>
+
+<li>デフォルトでは、アプリケーションごとに固有の Linux ユーザー ID が割り当てられます。権限が設定されているため、アプリケーションのファイルはそのユーザーからしか認識できず、そのアプリケーション自体からのみ利用できます。ただし、ファイルを他のアプリケーションにエクスポートすることは可能です。</li>
+</ul>
+
+<p>
+2 つのアプリケーションで同じユーザー ID を共有することもできます。その場合は、それぞれのアプリケーションのファイルを相互に認識できます。システム リソースを節約するため、同じ ID のアプリケーションで同じ VM を共有し、同じ Linux プロセスで実行することも可能です。
+</p>
+
+
+<h2 id="appcomp">アプリケーションのコンポーネント</h2>
+
+<p>
+Android の大きな特長の 1 つは、許可されていれば、あるアプリケーションから別のアプリケーションの要素を利用できる点です。たとえば、開発中のアプリケーションで画像の一覧をスクロール表示したい場合、他のアプリケーションで開発済みの適切なスクローラがあり、その利用が許可されていれば、独自に開発しなくてもそのスクローラを利用できます。アプリケーションに他のアプリケーションのコードを組み込んだり、リンクを設定したりする必要はありません。必要になった時点で、他のアプリケーションの一部分を開始するだけです。
+</p>
+
+<p>
+この仕組みが機能するには、アプリケーション プロセスの一部分を必要に応じて開始でき、その部分の Java オブジェクトをインスタンス化できなくてはなりません。そのため、Android アプリケーションには、他のシステムで動作するアプリケーションでよく使用されるような、アプリケーション全体にアクセスするための単一のエントリ ポイント(たとえば {@code main()} 関数)はありません。代わりに、システムが必要に応じてインスタンス化して実行できるコンポーネントで構成されます。<i></i>コンポーネントには以下の 4 つのタイプがあります:
+</p>
+
+<dl>
+
+<dt><b>アクティビティ</b></dt>
+<dd>アクティビティは、ユーザーが 1 つの操作を集中的に行うための視覚的なユーザー インターフェースを表します。<i></i>たとえば、ユーザーが選択できるメニュー アイテムの一覧を表示するアクティビティや、写真をキャプション付きで表示するアクティビティなどが考えられます。SMS アプリケーションなら、あるアクティビティでメッセージを送信する連絡先の一覧を表示し、別のアクティビティで選択した連絡先へのメッセージを入力し、その他のアクティビティで古いメッセージを参照したり設定を変更したりできます。これらのアクティビティを組み合わせて全体としてのユーザー インターフェースを形成しますが、それぞれのアクティビティは相互に独立しています。各アクティビティは、{@link android.app.Activity} 基本クラスのサブクラスとして実装されます。  
+
+<p>
+アプリケーションは、1 つのアクティビティで構成することも、上記のSMS アプリケーションのように複数のアクティビティで構成することもできます。どのようなアクティビティがいくつ必要になるかは、アプリケーションやその設計に応じて異なります。通常は、アクティビティのうちのいずれかを最初のアクティビティとして指定し、ユーザーがアプリケーションを起動したときに表示します。あるアクティビティから別のアクティビティに移動するには、現在のアクティビティから次のアクティビティを開始します。  
+</p>
+
+<p>
+各アクティビティには、それを表示するためのデフォルトのウィンドウが割り当てられます。通常はウィンドウを画面全体に表示しますが、画面より小さいウィンドウを他のウィンドウの前面に表示することもできます。アクティビティに、新たなウィンドウを追加することも可能です。たとえば、アクティビティの途中でユーザーの応答を要求するポップアップ ダイアログを表示したり、ユーザーが画面上の特定のアイテムを選択したときに別ウィンドウで重要な情報を表示したりできます。
+</p>
+
+<p>
+ウィンドウの視覚的なコンテンツは、ビュー({@link android.view.View} 基本クラスの派生オブジェクト)の階層として提供されます。各ビューは、ウィンドウ内の特定の矩形領域を制御します。親ビューは、その子となるビューで構成され、それらの子ビューのレイアウトを決定します。リーフ ビュー(階層の最下位に位置するビュー)は、そのビューが制御する矩形領域に表示され、その領域でのユーザーのアクションに対して応答します。つまり、ビューはアクティビティとユーザーが対話する場所です。たとえば、ビューに小さな画像を表示し、ユーザーがその画像をタップしたら何らかのアクションを開始することもできます。Android には、ボタン、テキスト フィールド、スクロール バー、メニュー アイテム、チェックボックスなど、さまざまなビューがあらかじめ用意されています。
+</p>
+
+<p>
+ビューの階層は、<code>{@link android.app.Activity#setContentView Activity.setContentView()}</code> メソッドを使用してアクティビティのウィンドウ内に配置します。コンテンツ ビューは、階層のルートとなる View オブジェクトです<i></i>(ビューおよびその階層について詳しくは<a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> のドキュメントをご覧ください)。
+</p>
+
+<p><dt><b>サービス</b></dt>
+<dd>サービスは、視覚的なユーザー インターフェースを持たず、バックグラウンドにおいて明確な終了期限がなくで実行されます。<i></i>たとえば、ユーザーが他の操作をしている間 BGM を再生するサービス、ネットワーク経由でデータをフェッチするサービス、何かを計算してその結果をアクティビティに提供するサービスなどが考えられます。各サービスは、{@link android.app.Service} 基本クラスの拡張です。
+
+<p>
+典型的な例としては、プレイリストの曲を再生するメディア プレーヤーが挙げられます。プレーヤー アプリケーションは、ユーザーが曲を選んで再生するための 1 つ以上のアクティビティで構成することが予想されますが、ユーザーはプレーヤーを離れて別の操作に移った後も曲を聞いていたいと考えられることから、曲の再生自体をアクティビティで処理するわけにはいきません。音楽の再生を続けるには、メディア プレーヤー アクティビティから、バックグラウンドで実行するサービスを開始します。音楽再生サービスは、それを開始したアクティビティが画面上に見えなくなった後もそのまま実行されます。
+</p>
+
+<p> 
+また、実行中のサービスに接続(バインド)することもできます(実行されていない場合はそのサービスを開始することも可能です)。接続中は、サービスが公開しているインターフェースを使ってサービスと対話できます。音楽再生サービスであれは、このインターフェースを使って一時停止、巻き戻し、停止、再生の再開などの操作を実行できるようにします。
+</p>
+
+<p>
+アクティビティや他のコンポーネントと同様に、サービスもアプリケーション プロセスのメイン スレッドで実行します。したがって、サービスによって他のコンポーネントやユーザー インターフェースの実行を妨げられることはなく、時間がかかるタスク(たとえば曲の再生)については、通常は別のスレッドを生成して処理します。詳しくは、<a href="#procthread">プロセスとスレッド</a>をご覧ください。
+</p></dd>
+
+<dt><b>ブロードキャスト レシーバ</b></dt>
+<dd>ブロードキャスト レシーバは、ブロードキャストの連絡を受信してそれに対処するだけのコンポーネントです。<i></i>ブロードキャストの多くが元々はシステム コードで、たとえばタイム ゾーンが変更されたこと、電池の残量が少なくなったこと、写真が撮影されたこと、ユーザーが言語設定を変更したことなどを連絡するために使用します。アプリケーションでも、たとえば何らかのデータがデバイスにダウンロードされて利用できるようになったことを、他のアプリケーションにブロードキャストで知らせることができます。
+
+<p>
+アプリケーションでは、重要と思われるすべての連絡に応答できるよう、ブロードキャスト レシーバをいくつでも設定できます。すべてのレシーバは、{@link android.content.BroadcastReceiver} 基本クラスの拡張です。
+</p>
+
+<p>
+ブロードキャスト レシーバがユーザー インターフェースを表示することはありません。ただし、受信した情報への応答としてアクティビティを開始したり、{@link android.app.NotificationManager} を使用してユーザーにアラートを送信したりすることはあります。通知の際には、バックライトを点滅させる、バイブレーションを起動する、音を鳴らすなど、さまざまな方法でユーザーの注意を喚起できます。通常は、ステータス バーに永続アイコンを表示し、ユーザーがこれを開いてメッセージを取得できるようにします。 
+</p></dd>
+
+<dt><b>コンテンツ プロバイダ</b></dt>
+<dd>コンテンツ プロバイダは、アプリケーションのデータを他のアプリケーションでも利用できるようにします。<i></i>データは、ファイル システムや SQLite データベースなど、一般に利用できる方法で格納されていれば使用できます。コンテンツ プロバイダは、{@link android.content.ContentProvider} 基本クラスの拡張です。プロバイダが制御する型のデータを、他のアプリケーションから取得および格納するための標準メソッド セットを実装しています。ただし、これらのメソッドをアプリケーションから直接呼び出すことはできません。代わりに、{@link android.content.ContentResolver} オブジェクトのメソッドを呼び出します。ContentResolver は、すべてのプロバイダと通信でき、プロバイダと連携して関係のあるすべてのプロセス間通信を管理します。 
+
+<p>
+コンテンツ プロバイダの使用方法について詳しくは、<a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>のドキュメントをご覧ください。
+</p></dd>
+
+</dl>
+
+<p>
+Android では、特定のコンポーネントで処理すべきリクエストがあると、そのコンポーネントのアプリケーション プロセスが実行中かどうかを確認(必要に応じてプロセスを開始)し、そのコンポーネントの適切なインスタンスが利用可能かどうかを確認(必要に応じてインスタンスを作成)します。  
+</p>
+
+
+<h3 id="actcomp">コンポーネントのアクティブ化: インテント</h3> 
+
+<p>
+コンテンツ プロバイダは、ContentResolver からのリクエストの対象になるとアクティブ化されます。それ以外の 3 つのコンポーネント(アクティビティ、サービス、ブロードキャスト レシーバ)は、インテントと呼ばれる非同期メッセージによってアクティブ化されます。<i></i>インテントは、メッセージのコンテンツを保持する {@link android.content.Intent} オブジェクトです。アクティビティやサービスの場合の Intent オブジェクトの主な役割は、リクエストされているアクションを指名し、その対象となるデータの URI を指定することです。たとえば、ユーザーに画像を表示するためのリクエストや、ユーザーにテキストを編集させるリクエストをアクティビティに伝達できます。ブロードキャスト レシーバの場合は、Intent オブジェクトがこれから通知を行うアクションを指名します。たとえば、カメラのボタンが押されたことを、関係のあるブロードキャスト レシーバに通知できます。
+</p>
+
+<p>
+以下に示すように、コンポーネントのタイプごとに別々のアクティブ化メソッドが用意されています: 
+</p>
+
+<ul>
+
+<li>アクティビティを起動する(または何か新しい処理を実行させる)には、Intent オブジェクトを <code>{@link android.content.Context#startActivity 
+Context.startActivity()}</code> または <code>{@link 
+android.app.Activity#startActivityForResult 
+Activity.startActivityForResult()}</code> に渡します。応答アクティビティで <code>{@link android.app.Activity#getIntent getIntent()}</code> メソッドを呼び出すと、最初にそのアクティビティが起動されたときのインテントの内容を確認できます。Android によってアクティビティの <code>{@link 
+android.app.Activity#onNewIntent onNewIntent()}</code> メソッドが呼び出され、アクティビティが後続のインテントに渡されます。
+
+<p>
+多くの場合、アクティビティから次のアクティビティを開始します。開始するアクティビティから結果が返される場合は、{@code startActivity()} ではなく {@code startActivityForResult()} を呼び出します。たとえば、ユーザーに写真を選択させるアクティビティを開始する場合は、ユーザーによって選択された写真が返されるかもしれません。結果は、呼び出し側のアクティビティの <code>{@link android.app.Activity#onActivityResult 
+onActivityResult()}</code> メソッドに渡した Intent オブジェクトで返されます。
+</p>
+</li>
+
+<li><p>サービスを開始する(または実行中のサービスに新しい指示を与える)には、<code>{@link 
+android.content.Context#startService Context.startService()}</code> に Intent オブジェクトを渡します。Android により、サービスの <code>{@link android.app.Service#onStart 
+onStart()}</code> メソッドが呼び出されて Intent オブジェクトが渡されます。</p>
+
+<p>
+同様に、インテントを <code>{@link 
+android.content.Context#bindService Context.bindService()}</code> に渡すと、呼び出し側のコンポーネントと対象となるサービスの間の継続中の接続を確立できます。サービスは、<code>{@link android.app.Service#onBind onBind()}</code> 呼び出しで Intent オブジェクトを受け取ります(サービスがまだ開始されていない場合は、必要に応じて {@code bindService()} で開始できます)。たとえば、上で例に挙げた音楽再生サービスとの接続を確立するアクティビティを使用して、ユーザーが再生を操作するための手段(ユーザー インターフェース)を提供できます。アクティビティで {@code bindService()} を呼び出して接続を確立してから、サービスに定義されているメソッドを呼び出して再生を操作します。
+</p>
+
+<p>
+サービスのバインドについては、後ほど<a href="#rpc">リモート プロシージャ コール</a>のセクションで詳しく説明します。
+</p>
+</li>
+
+<li><p>アプリケーションでブロードキャストを開始するには、<code>{@link 
+android.content.Context#sendBroadcast(Intent) Context.sendBroadcast()}</code>、<code>{@link android.content.Context#sendOrderedBroadcast(Intent, String) 
+Context.sendOrderedBroadcast()}</code>、<code>{@link 
+android.content.Context#sendStickyBroadcast Context.sendStickyBroadcast()}</code> などのメソッドのいずれかのバリエーションに Intent オブジェクトを渡します。Android によって <code>{@link 
+android.content.BroadcastReceiver#onReceive onReceive()}</code> メソッドが呼び出され、関係のあるすべてのブロードキャスト レシーバにインテントが配信されます。</p></li>
+
+</ul>
+
+<p>
+インテント メッセージについて詳しくは、<a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a> をご覧ください。
+</p>
+
+
+<h3 id="endcomp">コンポーネントの終了</h3>
+
+<p>
+コンテンツ プロバイダは、ContentResolver からのリクエストに応答している間のみアクティブになります。ブロードキャスト レシーバは、ブロードキャスト メッセージに応答している間のみアクティブになります。つまり、これらのコンポーネントを明示的に終了させる必要はありません。
+</p>
+
+<p>
+一方、アクティビティはユーザー インターフェースを提供します。長い時間をかけてユーザーと会話するためのものであり、待機状態の間も、会話が続いてきる限りはアクティブなままになっている可能性があります。同様に、サービスも長い間実行されたままになる可能性があります。Android には、アクティビティとサービスを以下のような規則的な方法で終了させるためのメソッドが用意されています:
+</p>
+
+<ul>
+<li>アクティビティを終了させるには、その <code>{@link android.app.Activity#finish finish()}</code> メソッドを呼び出します。あるアクティビティから {@code startActivityForResult()} で開始した別のアクティビティは、<code>{@link android.app.Activity#finishActivity finishActivity()}</code> を呼び出して終了させることができます。</li>
+
+<li>サービスは、その <code>{@link android.app.Service#stopSelf stopSelf()}</code> メソッドを呼び出すか、<code>{@link android.content.Context#stopService Context.stopService()}</code> を呼び出すことで停止できます。</li>
+</ul>
+
+<p>
+コンポーネントが、既に利用されていない場合や、Android がよりアクティブな他のコンポーネントにメモリを割り当てる必要がある場合は、システムがコンポーネントを終了させることもあります。このような状況およびその影響については、<a href="#lcycles">コンポーネントのライフサイクル</a>で詳しく説明します。
+</p>
+
+
+<h3 id="manfile">マニフェスト ファイル</h3>
+
+<p>
+アプリケーション コンポーネントを開始するには、Android がそのコンポーネントの存在を認識している必要があります。アプリケーションのコンポーネントは、マニフェスト ファイルで宣言します。このファイルは、アプリケーションのコード、ファイル、リソースなどとともに Android パッケージ({@code .apk} ファイル)にバンドルされます。  
+</p>
+
+<p>
+マニフェストは構造化された XML ファイルで、どのアプリケーションでも常に AndroidManifest.xml という名前になります。アプリケーション コンポーネントの宣言以外にも、アプリケーションをリンクさせる必要のあるライブラリ(デフォルトの Android ライブラリを除く)の指定や、アプリケーションに付与されるべき権限の指定などにも使用します。
+</p>
+
+<p>
+しかし、マニフェストの最も重要な役割は、アプリケーションのコンポーネントに関する情報を Android に提供することです。たとえば、アクティビティを次のように宣言できます:
+</p>
+
+<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;manifest . . . &gt;
+    &lt;application . . . &gt;
+        &lt;activity android:name="com.example.project.FreneticActivity"
+                  android:icon="@drawable/small_pic.png"
+                  android:label="@string/freneticLabel" 
+                  . . .  &gt;
+        &lt;/activity&gt;
+        . . .
+    &lt;/application&gt;
+&lt;/manifest&gt;</pre>
+
+<p>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> 要素の {@code name} 属性は、そのアクティビティを実装する {@link android.app.Activity} サブクラスを指名します。{@code icon} および {@code label} 属性には、ユーザーに対して表示するアイコンやラベルが保持されているリソース ファイルを指定します。
+</p>
+
+<p>
+その他のコンポーネントも、サービスは <code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code> 要素、ブロードキャスト レシーバは <code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code> 要素、コンテンツ プロバイダは <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code> 要素を使用して同じような方法で宣言します。マニフェストに宣言されていないアクティビティ、サービス、およびコンテンツ プロバイダは、システムから認識できないため実行されることはありません。ただし、ブロードキャスト レシーバの場合は、マニフェストで宣言する方法と、コード内で {@link android.content.BroadcastReceiver} オブジェクトとして動的に作成し、<code>{@link android.content.Context#registerReceiver Context.registerReceiver()}</code> を呼び出してシステムに登録する方法があります。
+</p>
+
+<p>
+マニフェスト ファイルの作成方法について詳しくは、<a href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a>をご覧ください。
+</p>
+
+
+<h3 id="ifilters">インテント フィルタ</h3>
+
+<p>
+Intent オブジェクトでは、対象とするコンポーネントを明示的に指名できます。明示的に指名されている場合、Android はマニフェスト ファイル内の宣言に基づいてコンポーネントを特定してアクティブにします。一方、明示的に指名されていない場合は、そのインテントに応答する上で最適なコンポーネントが選択されます。方法としては、Intent オブジェクトを、その対象となりうるコンポーネントのインテント フィルタと照合します。<i></i>コンポーネントのインテント フィルタは、そのコンポーネントで処理できるインテントの種類を示します。これもコンポーネントに関する重要な情報の 1 つなので、マニフェスト ファイルで宣言します。次に、上に示した例を拡張して 2 つのインテント フィルタを追加したアクティビティを示します:
+</p>
+
+<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;manifest . . . &gt;
+    &lt;application . . . &gt;
+        &lt;activity android:name="com.example.project.FreneticActivity"
+                  android:icon="@drawable/small_pic.png"
+                  android:label="@string/freneticLabel" 
+                  . . .  &gt;
+            &lt;intent-filter . . . &gt;
+                &lt;action android:name="android.intent.action.MAIN" /&gt;
+                &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
+            &lt;/intent-filter&gt;
+            &lt;intent-filter . . . &gt;
+                &lt;action android:name="com.example.project.BOUNCE" /&gt;
+                &lt;data android:mimeType="image/jpeg" /&gt;
+                &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+            &lt;/intent-filter&gt;
+        &lt;/activity&gt;
+        . . .
+    &lt;/application&gt;
+&lt;/manifest&gt;</pre>
+
+<p>
+この例の 1 つ目のフィルタは、アクション「{@code android.intent.action.MAIN}」とカテゴリ「{@code android.intent.category.LAUNCHER}」を組み合わせた一般的なフィルタです。このフィルタは、アプリケーション ランチャ(ユーザーがデバイス上で起動できるアプリケーションを一覧表示した画面)に、このアクティビティを表示する必要があることを示しています。つまり、このアクティビティはアプリケーションへのエントリ ポイントとして機能し、ユーザーがランチャでそのアプリケーションを選択したときに最初に表示されるということです。
+</p>
+
+<p>
+2 つ目のフィルタでは、アクティビティが特定のタイプのデータに対して実行できるアクションを宣言しています。
+</p>
+
+<p>
+コンポーネントにはインテント フィルタをいくつでも指定でき、それぞれのフィルタで別々の機能を宣言できます。フィルタが 1 つも指定されていないコンポーネントは、そのコンポーネントが対象として明示的に指名されているインテントでのみアクティブにできます。
+</p>
+
+<p>
+コード内で作成して登録したブロードキャスト レシーバの場合、インテント フィルタは {@link android.content.IntentFilter} オブジェクトとして直接インスタンス化されます。それ以外の全てのフィルタは、マニフェストで設定します。
+</p>
+
+<p>
+インテント フィルタについて詳しくは、<a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a> をご覧ください。
+</p>
+
+
+<h2 id="acttask">アクティビティとタスク</h2>
+
+<p>
+既に説明したように、あるアクティビティから別のアクティビティを開始することができます。これには、別のアプリケーションで定義されているアクティビティも含まれます。たとえば、ユーザーに特定の場所の地図を表示するとします。そのためのアクティビティは既に存在しているので、現在のアクティビティで必要な情報を Intent オブジェクトに格納して {@code startActivity()} に渡すだけで、マップ ビューアに地図を表示できます。ユーザーが [戻る] キーを押すと、画面に元のアクティビティが再表示されます。
+</p>
+
+<p>
+この場合、マップ ビューアは別のアプリケーションで定義されており、そのアプリケーションのプロセスで実行されていますが、ユーザーにとってはマップ ビューアが元のアプリケーションの一部であるかのように感じられます。Android では、両方のアクティビティを同じタスクに組み込むことで、このようなユーザー エクスペリエンスを実現できます。<i></i>簡単に言えば、ユーザーが 1 つの「アプリケーション」と感じるものがタスクです。関連するアクティビティをスタックにまとめたものがタスクです。スタック内のルート アクティビティは、タスクを開始するアクティビティです。通常であれば、ユーザーがアプリケーション ランチャで選択するアクティビティがこれに相当します。スタックの最上位にあるアクティビティは、ユーザーのアクションの焦点となっている実行中のアクティビティです。あるアクティビティから別のアクティビティを開始すると、そのアクティビティが新たにスタックにプッシュされて実行中のアクティビティになります。1 つ前のアクティビティはスタック内に残されています。ユーザーが [[]戻る] キーを押すと、現在のアクティビティがスタックからポップされ、1 つ前のアクティビティが実行中のアクティビティとして再開されます。  
+</p>
+
+<p>
+スタックはオブジェクトを保持します。したがって、同じ Activity サブクラスのインスタンス(たとえばマップ インスタンス)を複数開くと、それぞれのインスタンスが別々のエントリになります。スタック内のアクティビティは、プッシュまたはポップされるのみで再配置されることはありません。
+</p>
+
+<p>
+タスクはアクティビティのスタックであり、マニフェスト ファイル内のクラスや要素ではありません。したがって、アクティビティと無関係にタスクの値を設定することはできません。タスクの値は、ルート アクティビティでまとめて設定します。たとえば、次のセクションでは「タスクの親和性」について説明しますが、値はタスクのルート アクティビティの親和性のセットから読み込まれます。
+</p>
+
+<p>
+タスク内のアクティビティは、1 つのユニットとして一緒に移動します。タスク全体(アクティビティ スタック全体)をフォアグラウンドに移動したり、バックグラウンドに移動したりできます。たとえば、現在のタスクは 4 つのアクティビティからなるスタックで、現在のアクティビティの下にアクティビティが 3 つあるとします。ここで、ユーザーが [ホーム] キーを押してアプリケーション ランチャに移動し、新しいアプリケーション(実際には新しいタスク)を選択したとします。<i></i>すると、現在のタスクはバックグラウンドに移動し、新しいタスクのルート アクティビティが表示されます。しばらくして、ユーザーがホーム画面に戻り 1 つ前のアプリケーション(タスク)を選択すると、そのタスクがスタック内の 4 つのアクティビティとともにフォアグラウンドに移動します。ここでユーザーが [戻る] キーを押しても、中断したばかりのアプリケーション(1 つ前のタスクのルート アクティビティ)は表示されません。代わりに、スタックの最上位のアクティビティがポップされ、同じタスクの 1 つ前のアクティビティが表示されます。 
+</p>
+
+<p>
+アクティビティとタスクの動作としては、ここで説明した動作がデフォルトです。ただし、この動作のほとんどの要素は変更可能です。タスクとアクティビティの関連付けやタスク内でのアクティビティの動作は、アクティビティを開始した Intent オブジェクトのフラグ セットと、マニフェストに指定されているアクティビティの <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> 要素の属性セットとの相互作用によって決まります。リクエスト側と応答側の両方が動作に影響を及ぼします。
+</p>
+
+<p>
+この点において、主に使用する Intent フラグは以下のとおりです:
+
+<p style="margin-left: 2em">{@code FLAG_ACTIVITY_NEW_TASK} <br/>{@code FLAG_ACTIVITY_CLEAR_TOP} <br/>{@code FLAG_ACTIVITY_RESET_TASK_IF_NEEDED} <br/>{@code FLAG_ACTIVITY_SINGLE_TOP}</p>
+
+<p>
+また、主に使用する {@code &lt;activity&gt;} 属性は以下のとおりです:
+  
+<p style="margin-left: 2em">{@code taskAffinity} <br/>{@code launchMode} <br/>{@code allowTaskReparenting} <br/>{@code clearTaskOnLaunch} <br/>{@code alwaysRetainTaskState} <br/>{@code finishOnTaskLaunch}</p>
+
+<p>
+以降のセクションでは、これらのフラグや属性の役割、相互作用の仕組み、使用する際の留意事項などについて説明します。
+</p>
+
+
+<h3 id="afftask">親和性と新しいタスク</h3>
+
+<p>
+デフォルトでは、アプリケーション内のすべてのアクティビティは相互に親和性があり、すべてのアクティビティができる限り同じタスクに属そうとします。<i></i>ただし、{@code &lt;activity&gt;} 要素の {@code taskAffinity} 属性を使用して、アクティビティごとに個別の親和性を設定することもできます。つまり、別々のアプリケーションで定義されているアクティビティで親和性を共有したり、同じアプリケーションで定義されているアクティビティに別々の親和性を割り当てたりできるということです。親和性が作用する状況は 2 つあります。1 つはアクティビティを起動する Intent オブジェクトに {@code FLAG_ACTIVITY_NEW_TASK} フラグが含まれている場合、もう 1 つはアクティビティの {@code allowTaskReparenting} 属性が "{@code true}" に設定されている場合です。 
+</p>
+
+<dl>
+<dt><code>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</code> フラグ</dt>
+<dd>既に説明したとおり、新しいアクティビティは、デフォルトでは {@code startActivity()} を呼び出したアクティビティのタスクの一部として起動します。つまり、呼び出し側のアクティビティと同じスタックにプッシュされるということです。しかし、{@code startActivity()} に渡された Intent オブジェクトに {@code FLAG_ACTIVITY_NEW_TASK} フラグが含まれている場合、システムはその新しいアクティビティを別のタスクに収容しようとします。フラグの名前からも判断できますが、ほとんどの場合は新しいタスクが開始されます。ただし常にそうなるとは限りません。既存のタスクに新しいアクティビティと同じ親和性が割り当てられている場合、そのアクティビティはそのタスクの一部として起動します。そうでない場合には、新しいタスクが開始されます。</dd>
+
+<dt><code><a 
+href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">allowTaskReparenting</a></code> 属性</dt>
+<dd>{@code allowTaskReparenting} 属性が "{@code true}" に設定されているアクティビティは、そのアクティビティと親和性のあるタスクがフォアグラウンドに移ったときに、アクティビティを開始したタスクから親和性のあるタスクに移動できます。たとえば、旅行アプリケーションの一部として、選択された都市の天気予報を表示するアクティビティが定義されているとします。このアクティビティには、同じアプリケーション内の他のアクティビティと同じ親和性(デフォルトの親和性)が割り当てられていますが、その親の割り当てを変更することも可能です。あるアクティビティが天気予報アクティビティを開始すると、その時点では開始側のアクティビティと同じタスクに属した状態になります。しかし、次に旅行アプリケーションがフォアグラウンドに移ると、天気予報アクティビティの割り当てが変更され、旅行アプリケーションのタスクの一部として表示されます。</dd>
+</dl>
+
+<p>
+ユーザーから見て複数の「アプリケーション」が 1 つの {@code .apk} ファイルに含まれている場合は、それぞれのアプリケーションに関連付けられているアクティビティに別々の親和性を割り当てることをおすすめします。
+</p>
+
+
+<h3 id="lmodes">起動モード</h3>
+
+<p>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launchMode</a></code> 属性の {@code &lt;activity&gt;} 要素には、以下の 4 種類の起動モードを割り当てることができます:
+</p>
+
+<p style="margin-left: 2em">"{@code standard}"(デフォルト モード)<br>"{@code singleTop}"<br>"{@code singleTask}"<br>"{@code singleInstance}"</p>
+
+<p>
+これらのモードは、それぞれが以下の 4 つの点で異なります:
+</p>
+
+<ul>
+
+<li><b>インテントに応答するアクティビティをどのタスクに保持するか</b>。"{@code standard}" および "{@code singleTop}" モードの場合は、そのインテントを開始した(つまり <code>{@link android.content.Context#startActivity startActivity()}</code> を呼び出した)タスクに保持されます。ただし、Intent オブジェクトに <code>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</code> フラグが含まれている場合は、前のセクション<a href="#afftask">親和性と新しいタスク</a>で説明したとおり、別のタスクが選択されます。  
+
+<p>
+一方、"{@code singleTask}" および "{@code singleInstance}" モードの場合は、アクティビティが常にタスクのルート アクティビティになります。タスクは定義されており、他のタスクの一部として起動されることはありません。
+</p>  
+
+<li><p><b>アクティビティのインスタンスを複数生成できるか</b>。"{@code standard}" または "{@code singleTop}" アクティビティは複数回インスタンス化できます。それらのインスタンスを複数のタスクに割り当てることも、特定のタスクに同じアクティビティの複数のインスタンスを割り当てることも可能です。
+</p> 
+
+<p>
+一方、"{@code singleTask}" および "{@code singleInstance}" アクティビティのインスタンスは 1 つに制限されます。これらのアクティビティはタスクのルートに当たります。したがって、これらのタスクの複数のインスタンスがデバイス上に同時に存在することはないということになります。
+</p>    
+
+<li><p><b>インスタンスのタスクに他のアクティビティを含めることができるか</b>。"{@code singleInstance}" アクティビティは、そのタスク内の唯一のアクティビティとして単独で動作します。ここから別のアクティビティを開始した場合、そのアクティビティは起動モードに関係なく、あたかもインテントに {@code FLAG_ACTIVITY_NEW_TASK} フラグが含まれているかのように別のタスクで起動します。"{@code singleInstance}" モードと "{@code singleTask}" モードは、これ以外の点ではまったく同じです。</p>
+
+<p>
+他の 3 つのモードでは、タスクに複数のアクティビティを割り当てることができます。"{@code singleTask}" アクティビティは、常にタスクのルート アクティビティになりますが、同じタスクに割り当てることになる別のアクティビティを開始することができます。"{@code standard}" および "{@code singleTop}" アクティビティのインスタンスは、スタック内のどの位置にでも配置できます。  
+</p></li>
+
+<li><b>クラスの新しいインスタンスを起動して新しいインテントを処理するかどうか</b>。デフォルトの "{@code standard}" モードの場合は、新しいインテントに応答するときには必ず新しいインスタンスが作成されます。それぞれのインスタンスで処理するインテントは 1 つのみです。"{@code singleTop}" モードの場合は、クラスの既存のインスタンスが対象タスクのアクティビティ スタックの最上位にあれば、それを再利用して新しいインテントを処理します。スタックの最上位にない場合は再利用されません。代わりに、新しいインスタンスが作成されてスタックにプッシュされ、新しいインテントの処理に使用されます。
+
+<p>
+たとえば、タスクのアクティビティ スタックに、ルート アクティビティ A とアクティビティ B、C、D が含まれているとします。スタック内のアクティビティの順序は A-B-C-D で D が最上位です。ここに、アクティビティのタイプが D のインテントが届きます。D の起動モードがデフォルトの "{@code standard}" である場合は、そのクラスの新しいインスタンスが起動し、スタックは A-B-C-D-D となります。しかし、D の起動モードが "{@code singleTop}" であれば、スタックの最上位は D なので、新しいインテントは既存のインスタンスによって処理されるはずです。したがって、スタックは A-B-C-D のままとなります。  
+</p>
+
+<p>
+一方、届いたインテントのアクティビティ タイプが B だった場合は、B のモードが "{@code standard}" であっても "{@code singleTop}"であっても B の新しいインスタンスが起動します。これは B がスタックの最上位ではないためで、結果としてスタックは A-B-C-D-B となります。
+</p>
+
+<p>
+"{@code singleTask}" または "{@code singleInstance}" アクティビティの場合は、既に説明したとおり同時に複数のインスタンスが存在することはないため、インスタンスは常に新しいインテントを処理することになります。"{@code singleInstance}" アクティビティはスタック内の唯一のアクティビティであるため、常にスタックの最上位、つまりインテントを処理する位置にあります。一方、"{@code singleTask}" アクティビティは、スタック内の上位に他のアクティビティがある場合とない場合があります。上位にアクティビティがある場合、インテントを処理する位置にはないため、そのインテントはドロップされます(インテントがドロップされたとしても、そのインテントが届いたことによって、タスクがフォアグラウンドに移ったままの状態になります)。
+</p>
+</li>
+
+</ul>
+
+<p>
+既存のアクティビティで新しいインテントを処理することになった場合は、<code>{@link android.app.Activity#onNewIntent onNewIntent()}</code> の呼び出しによって Intent オブジェクトがアクティビティに渡されます(最初にアクティビティを開始したインテント オブジェクトは <code>{@link android.app.Activity#getIntent getIntent()}</code> を呼び出して取得できます)。
+</p>
+
+<p>
+なお、新しいインテントを処理するためにアクティビティの新しいインスタンスが作成された場合、ユーザーは [[]戻る] キーを押して 1 つ前の状態(1 つ前のアクティビティ)に戻ることができます。しかし、アクティビティの既存のインスタンスで新しいインテントを処理する場合は、[[]戻る] キーを押しても、新しいインテントが届く前にそのインスタンスで処理していた作業に戻ることはできません。
+</p>
+
+<p>
+起動モードについて詳しくは、<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> 要素の説明をご覧ください。 
+</p>
+
+
+<h3 id="clearstack">スタックのクリア</h3>
+
+<p>
+ユーザーがタスクを長時間放置すると、タスクのルート アクティビティを除くすべてのアクティビティがクリアされます。ユーザーがタスクに戻ると、タスクは以前のように表示されますが、残っているのは最初のアクティビティだけです。つまり、一定の時間が経過していればユーザーは以前の作業を放棄していて、新しい作業をするためにそのタスクに戻ってきたと考えるわけです。
+</p>
+
+<p>
+これがデフォルトです。この動作を変更したい場合は、以下のアクティビティ属性を使用します:
+</p>
+
+<dl>
+<dt><code><a 
+href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetainTaskState</a></code> 属性</dt>
+<dd>タスクのルート アクティビティでこの属性を "{@code true}" に設定すると、上で説明したデフォルトの動作は発生しません。長時間経過しても、タスク内のすべてのアクティビティはそのまま残されます。</dd>
+
+<dt><code><a 
+href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch</a></code> 属性</dt>
+<dd>タスクのルート アクティビティでこの属性を "{@code true}" に設定した場合、ユーザーがいったんタスクを離れると、戻ったときにはルートを含むすべてのアクティビティがクリアされています。つまり、{@code alwaysRetainTaskState} の正反対の動作になります。ユーザーが一瞬でもタスクを離れると、最初の状態からやり直すことになります。</dd>
+
+<dt><code><a 
+href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTaskLaunch</a></code> 属性</dt>
+<dd>この属性は {@code clearTaskOnLaunch} に似ていますが、タスク全体ではなく単一のアクティビティに作用します。また、ルート アクティビティを含むどのアクティビティもクリアの対象となりえます。この属性が "{@code true}" に設定されたアクティビティは、現在のセッションの間のみタスクの一部を形成します。ユーザーがいったんそのタスクから離れてから、再度タスクに戻ると、このアクティビティはクリアされています</dd>
+</dl>
+
+<p>
+アクティビティをスタックから削除する方法は他にもあります。Intent オブジェクトに <code>{@link 
+android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP FLAG_ACTIVITY_CLEAR_TOP}</code> フラグが含まれており、そのインテントを処理すべきタイプのアクティビティのインスタンスが対象タスクのスタック内に存在する場合は、そのインスタンスがスタックの最上位になってインテントに応答できるよう、それより上位のアクティビティはすべてクリアされます。指定されたアクティビティの起動モードが "{@code standard}" である場合は、そのアクティビティもスタックから削除され、新しいインスタンスが起動してインテントを処理します。起動モード "{@code standard}" では、新しいインテントを処理する際、常に新しいインスタンスが作成されるためです。
+</p>
+
+<p>
+{@code FLAG_ACTIVITY_CLEAR_TOP} は、ほとんどの場合 {@code FLAG_ACTIVITY_NEW_TASK} と組み合わせて使用します。これらのフラグを組み合わせると、別のタスクに既に存在しているアクティビティを探し、それをインテントに応答できる位置に配置できます。  
+</p>
+
+
+<h3 id="starttask">タスクの開始</h3>
+
+<p>
+アクティビティをタスクのエントリ ポイントとして設定するには、アクションとして "{@code android.intent.action.MAIN}"、カテゴリとして "{@code android.intent.category.LAUNCHER}" を指定したインテント フィルタをアクティビティに追加します(このタイプのフィルタの例については、<a href="#ifilters">インテント フィルタ</a>をご覧ください)。このタイプのフィルタを追加すると、アクティビティのアイコンとラベルがアプリケーション ランチャに表示されます。これにより、ユーザーがタスクを起動するための手段を提供できるだけでなく、起動後はいつでもそのタスクに戻れるようにすることができます。
+</p>
+
+<p>
+この 2 番目の機能、つまりユーザーがいったんタスクを離れても後で戻ることができるようにする点が重要です。この理由から、アクティビティに {@code MAIN} と {@code LAUNCHER} フィルタが指定されている場合は、必ずタスクが開始される起動モード("{@code singleTask}" または "{@code singleInstance}")を使用する必要があります。たとえば、このフィルタを指定しなかった場合を考えてみましょう。インテントが "{@code singleTask}" アクティビティを起動し、新しいタスクが開始され、ユーザーがしばらくの間このタスクで作業を行います。その後、ユーザーが [ホーム] キーを押したとします。ホーム画面が表示され、先ほどのタスクはバックグラウンドに移動します。しかし、このタスクはアプリケーション ランチャには表示されていないため、ユーザーがタスクに戻るための手段がありません。
+</p>
+
+<p>
+{@code FLAG_ACTIVITY_NEW_TASK} フラグにも、これと同じような難しさがあります。このフラグを指定したアクティビティでは、新しいタスクを開始した後にユーザーが [ホーム] キーを押してそのタスクを離れた場合に備え、タスクに戻るための手段を用意しておく必要があります。一部のエンティティ(たとえば通知マネージャ)は、アクティビティを常に外部タスクとして開始します。エンティティの一部として開始することはないため、{@code startActivity()} に渡すインテントには必ず {@code FLAG_ACTIVITY_NEW_TASK} を指定します。外部エンティティから呼び出すことのできるアクティビティでこのフラグが使用されている可能性がある場合は、開始されたタスクにユーザーが戻るための手段を別途提供するようにしてください。
+</p> 
+
+<p>
+ユーザーがアクティビティに戻ることができるようにしない場合は、{@code &lt;activity&gt;} 要素の {@code finishOnTaskLaunch} を "{@code true}" に設定します。詳しくは、<a href="#clearstack">スタックのクリア</a>をご覧ください。
+</p>
+
+
+<h2 id="procthread">プロセスとスレッド</h2>
+
+<p>
+Android では、最初のアプリケーション コンポーネントを実行する必要が生じると、そのための Linux プロセスを単一の実行スレッドで開始します。デフォルトでは、アプリケーションのすべてのコンポーネントがそのプロセスとスレッドで実行されます。
+</p>
+
+<p>
+ただし、コンポーネントが他のプロセスで実行されるようにしたり、特定のプロセスに使用する追加スレッドを生成したりすることも可能です。
+</p>
+
+
+<h3 id="procs">プロセス</h3>
+
+<p>
+コンポーネントを実行するプロセスは、マニフェスト ファイルで管理します。コンポーネントの各要素({@code &lt;activity&gt;}、{@code &lt;service&gt;}、{@code &lt;receiver&gt;}、および {@code &lt;provider&gt;})には {@code process} 属性があり、そのコンポーネントをどのプロセスで実行すべきかを指定できるようになっています。これらの属性の設定によって、それぞれのコンポーネントを専用のプロセスで実行したり、一部のコンポーネントだけでプロセスを共有したりできます。また、別々のアプリケーションのコンポーネントが、同じプロセスで実行されるように設定することもできます。この場合は、それらのアプリケーションが同じ Linux ユーザー ID を共有し、同じ認証機関によって署名されている必要があります。{@code &lt;application&gt;} 要素にも {@code process} 属性があり、すべてのコンポーネントに適用されるデフォルト値を設定できます。
+</p>
+
+<p>
+すべてのコンポーネントは指定されたプロセスのメイン スレッドでインスタンス化され、コンポーネントに対するシステム コールはそのスレッドからディスパッチされます。1 つのインスタンスに対して、複数のスレッドが作成されることはありません。したがって、システム コールに応答するメソッド(たとえば、後ほど<a href="#lcycles">コンポーネント ライフサイクル</a>で説明するライフサイクル通知や、ユーザーのアクションを報告する <code>{@link android.view.View#onKeyDown View.onKeyDown()}</code> のようなメソッド)は、常にそのプロセスのメイン スレッドで実行されます。つまり、コンポーネントがシステムから呼び出されたときに、プロセス内の他のコンポーネントの実行を妨げないよう、実行に時間がかかる処理や他の妨げになることの多い処理(ネットワーク処理、ループ計算など)をできる限り避ける必要があるということです。時間がかかる処理には別のスレッドを生成できます。詳しくは、次の<a href="#threads">スレッド</a> セクションをご覧ください。
+</p>
+
+<p>
+状況によっては、Android がプロセスを終了させるべきと判断する場合があります。たとえば、メモリが不足してきた場合や、他のプロセスでユーザーにすばやく応答する必要がある場合です。プロセスが終了すると、そのプロセス内で実行されているアプリケーション コンポーネントは破棄されます。それらのコンポーネントで処理する作業がもう一度発生すると、そのためのプロセスが再び開始されます。
+</p>  
+
+<p>
+Android では、どのプロセスを終了させるかを判断するため、ユーザーにとっての相対的な重要度を重み付けして管理します。たとえば、アクティビティがまだ画面に表示されているプロセスを終了させるよりも、アクティビティが画面に表示されていないプロセスを終了させる方が合理的です。したがって、プロセスを終了させるかどうかは、そのプロセスで実行されているコンポーネントの状態に応じて判断されるということです。コンポーネントの状態については、後ほど<a href="#lcycles">コンポーネントのライフサイクル</a>で詳しく説明します。
+</p>
+
+
+<h3 id="threads">スレッド</h3>
+
+<p>
+アプリケーションを単一のプロセスに限定したとしても、バックグラウンドでの処理にスレッドが必要になることはよくあります。ユーザー インターフェースはユーザーのアクションに対して常にすばやく応答できなければならないため、アクティビティをホストするスレッドで、ネットワーク ダウンロードのような時間のかかる処理を一緒にホストしないようにする必要があります。すぐに完了しない可能性のあるすべての処理は、別のスレッドに割り当てるようにしてください。 
+</p>
+
+<p>
+スレッドは、標準の Java {@link java.lang.Thread} オブジェクトを使用してコード内で作成します。Android には、スレッドを管理するための便利なクラスが数多く用意されています。たとえば、スレッド内でメッセージ ループを実行するための {@link android.os.Looper}、メッセージを処理するための {@link android.os.Handler}、メッセージ ループでスレッドを設定するための {@link android.os.HandlerThread} などがあります。
+</p>
+
+
+<h3 id="rpc">リモート プロシージャ コール</h3>
+
+<p>
+Androidは軽量な仕組みのリモート・プロシージャ・コール (RPC) を採用しています。RPC とは、メソッドをローカルで呼び出しますが、実行はリモート(別のプロセス)で行い、その結果を呼び出し側に返します。そのためには、メソッド呼び出しとそれに付随するデータをオペレーティングシステムが解釈できるレベルまで分解してから、それらをローカルのプロセスとアドレス空間からリモートのプロセスとアドレス空間に転送し、リモートで呼び出しを再構築する必要があります。戻り値は、反対方向に転送しなければなりません。Android にはこの処理を行うためのコードがすべて用意されているため、RPC インターフェースを定義して実装するだけで RPC を利用できます。
+</p>
+
+<p>
+RPC インターフェースに含めることができるのはメソッドのみです。すべてのメソッドは、戻り値がない場合でも同期的に実行されます(つまり、リモート メソッドが完了するまでローカル メソッドがブロックされます)。
+</p>
+
+<p>
+このメカニズムを簡単に説明すると次のようになります。まず、シンプルなインターフェース定義言語(IDL)を使用して、実装したい RPC インターフェースを宣言します。<code><a href="{@docRoot}guide/developing/tools/aidl.html">aidl</a></code> ツールにより、RPC インターフェースの宣言から Java インターフェース定義が生成されます。この定義は、ローカルとリモートの両方のプロセスで使用する必要があります。定義には、次の図に示すように 2 つの内部クラスが含まれています:
+</p>
+
+<p style="margin-left: 2em">
+<img src="{@docRoot}images/binder_rpc.png" alt="RPC のメカニズム"  />
+</p>
+
+<p>
+これらの内部クラスには、IDL で宣言したインターフェースのリモート プロシージャ コールを管理するために必要なコードがすべて含まれています。どちらの内部クラスも {@link android.os.IBinder} インターフェースを実装します。一方の内部クラスは、ローカルのシステムで内部的に使用しますが、記述するコードでは無視しても構いません。もう一方の内部クラスはスタブと呼ばれ、{@link android.os.Binder} クラスを拡張します。スタブには、IPC(プロセス間通信)呼び出しを発生させるための内部コードに加え、IDL で宣言した RPC インターフェース内のメソッドの宣言が含まれます。これらのメソッドを実装するには、図に示すようにスタブをサブクラス化します。2つの内部クラスのうちの一方は、システムがローカルかつ内部的に使用するので、開発者が記述するコードでは無視してかまいません。... リモート側では、図のようにスタブをサブクラス化して、これらのメソッドを実装する必要があります。
+</p>
+
+<p>
+	通常、リモート プロセスはサービスで管理します。サービスなら、プロセスや他のプロセスへの接続に関する情報をシステムに伝えることができるからです。サービスには、{@code aidl} ツールで生成されたインターフェース ファイルと、RPC メソッドを実装するスタブ サブクラスの両方を持たせることになります。サービスのクライアントには、{@code aidl} ツールで生成されたインターフェース ファイルのみを持たせます。
+</p>
+
+<p>
+以下に、サービスとそのクライアントの間の接続がどのように設定されるかを示します:
+</p>
+
+<ul>
+<li>サービスのクライアント(ローカル側)には <code>{@link android.content.ServiceConnection#onServiceConnected
+onServiceConnected()}</code> および<code>{@link android.content.ServiceConnection#onServiceDisconnected
+onServiceDisconnected()}</code> メソッドが実装されているため、リモート サービスとの接続が確立されたときや切断されたときには通知を受けることができます。通知があり次第、<code>{@link android.content.Context#bindService bindService()}</code> を呼び出して接続を設定します。
+</li>  
+
+<li> 
+サービスの <code>{@link android.app.Service#onBind onBind()}</code> メソッドは、受け取ったインテント({@code bindService()} に渡されたインテント)に応じて、接続を承認または拒否するために実装します。接続が承認されると、接続を承認するのであれば、スタブ サブクラスのインスタンスを返します。
+</li>
+
+<li>サービスが接続を承認すると、Android がクライアントの {@code onServiceConnected()} メソッドを呼び出し、IBinder オブジェクト(サービスが管理するスタブ サブクラスのプロキシ)を渡します。クライアントは、このプロキシを介してリモートサービスを呼び出すことができます。  
+</li>
+</ul>
+
+<p>
+ここでは、説明を簡単にするため、RPC メカニズムの細かい点は省略しています。詳しくは、<a href="{@docRoot}guide/developing/tools/aidl.html">Designing a Remote Interface Using AIDL</a>、および {@link android.os.IBinder IBinder} クラスの説明をご覧ください。
+</p>  
+
+
+<h3 id="tsafe">スレッドセーフなメソッド</h3>
+
+<p>
+状況によっては実装したメソッドが複数のスレッドから呼び出されることもあるため、スレッドセーフな記述を心掛ける必要があります。
+</p>
+
+<p>
+前のセクションで説明した RPC のようにメソッドをリモートで呼び出すことができる場合は、このような状況が特に発生しやすくなります。IBinder オブジェクトに実装されているメソッドを IBinder と同じプロセスから呼び出すと、そのメソッドは呼び出し側のスレッドで実行されます。一方、別のプロセスからメソッドを呼び出した場合は、プロセスのメイン スレッドではなく、IBinder と同じプロセス内に保持されているスレッドのプールから選択されたスレッドで実行されます。たとえば、サービスの {@code onBind()} メソッドはそのサービスのプロセスのメイン スレッドから呼び出されるのに対し、{@code onBind()} から返されたオブジェクトに実装されているメソッド(たとえば RPC メソッドを実装するスタブ サブクラス)はプール内のスレッドから呼び出されます。サービスには複数のクライアントを割り当てることができるため、複数のプール スレッドを同じ IBinder に同時に割り当てることも可能です。したがって、IBinder メソッドはスレッドセーフになるように実装する必要があります。
+</p>  
+
+<p>
+同様に、コンテンツ プロバイダも別のプロセスからのデータ リクエストを受け取ることができます。ContentResolver および ContentProvider クラスはプロセス間通信の管理の詳細を隠蔽しますが、それらのリクエストに応答する ContentProvider メソッド(<code>{@link android.content.ContentProvider#query query()}</code>、<code>{@link android.content.ContentProvider#insert insert()}</code>、<code>{@link android.content.ContentProvider#delete delete()}</code>、<code>{@link android.content.ContentProvider#update update()}</code>、および <code>{@link android.content.ContentProvider#getType getType()}</code> メソッド)は、プロセスのメイン スレッドではなく、コンテンツ プロバイダのプロセス内のスレッドのプールから呼び出されます。これらのメソッドを同時に呼び出すことのできるメソッドの数に制限はありません。したがって、これらのメソッドもスレッドセーフになるように実装する必要があります。
+</p> 
+
+
+<h2 id="lcycles">コンポーネントのライフサイクル</h2>
+
+<p>
+アプリケーション コンポーネントにはライフサイクルがあります。ライフサイクルは、インテントへ応答することでのインスタンス化で始まり、そのインスタンスの破棄で終わります。この間、コンポーネントがアクティブなときとアクティブでないときがあり、アクティビティであればユーザーから見えるときと見えないときがあります。このセクションでは、アクティビティ、サービス、およびブロードキャスト レシーバのライフサイクルについて説明します。具体的には、それぞれがライフタイムの間に取ることのできる状態、状態の遷移を通知する方法、およびそれらの状態が、コンポーネントを実行しているプロセスが終了させられたり、インスタンスが破棄されたりする可能性への影響などについて説明します。
+</p> 
+
+
+<h3 id="actlife">アクティビティのライフサイクル</h3>
+
+<p>アクティビティは、基本的に以下の 3 つの状態を取ります:</p>
+
+<ul>
+<li> 状態がアクティブまたは実行中のアクティビティは、画面のフォアグラウンドに表示されている(つまり現在のタスクのアクティビティ スタックの最上位にある)アクティビティです。<em></em><em></em>これが、ユーザーのアクションの焦点となっているアクティビティです。</li>
+
+<li><p>状態が一時停止のアクティビティは、ユーザーのアクションの焦点から外れていますが、まだユーザーから見ることのできるアクティビティです。<em></em>つまり、それよりも前面に他のアクティビティが表示されていますが、そのアクティビティが透明か全画面表示でないかのどちらかで、一時停止しているアクティビティの一部が見えている状態です。一時停止しているアクティビティは、完全に動作しています(すべての状態やメンバー情報は保持されており、ウィンドウ マネージャにアタッチされたままになっています)。ただし、メモリが極端に不足した場合は、システムによって強制終了させられる可能性があります。</p></li>
+
+<li><p>状態が停止のアクティビティは、別のアクティビティに隠されて完全に見えなくなったアクティビティです。<em></em>すべての状態とメンバー情報はまだ保持しています。しかし、もうユーザーに対して表示されていないため、他でメモリが必要な場合は強制終了させられる可能性が高いアクティビティです。</p></li>
+</ul>
+
+<p>
+システムが一時停止または停止しているアクティビティをメモリから削除する場合は、アクティビティの {@link android.app.Activity#finish finish()} メソッドを呼び出して終了を要求するか、単純のそのプロセスを強制終了します。そのアクティビティをもう一度ユーザーに表示する際は、完全に再起動して以前の状態に復元する必要があります。
+</p>
+
+<p>
+アクティビティがある状態から別の状態に遷移すると、以下の protected メソッドに対する呼び出しによって変更が通知されます:
+</p>
+
+<p style="margin-left: 2em">{@code void onCreate(Bundle <i>savedInstanceState</i>)} <br/>{@code void onStart()} <br/>{@code void onRestart()} <br/>{@code void onResume()} <br/>{@code void onPause()} <br/>{@code void onStop()} <br/>{@code void onDestroy()}</p>
+
+<p>
+これらのメソッドはすべて、状態が変化したときに適切な処理を行うためにオーバーライドできるフックです。オブジェクトが初めてインスタンス化されたときに初期設定を行うため、すべてのアクティビティには <code>{@link android.app.Activity#onCreate onCreate()}</code> を実装する必要があります。多くのアクティビティには、データの変更をコミットするための <code>{@link android.app.Activity#onPause onPause()}</code> も実装します。これを実装しない場合は、何らかの方法でユーザーとの対話を停止できるようにしておく必要があります。
+</p>
+
+<div class="sidebox-wrapper">
+<div class="sidebox-inner">
+<h2>スーパークラスの呼び出し</h2>
+<p>
+どのアクティビティ ライフサイクル メソッドの実装でも、必ず最初にスーパークラス バージョンを呼び出す必要があります。次に例を示します:
+</p>
+
+<pre>protected void onPause() {
+    super.onPause();
+    . . .
+}</pre>
+</div>
+</div> 
+
+
+<p>
+これら 7 つのメソッドを使用すると、アクティビティのライフサイクル全体を定義できます。これらを実装することで、ネストされた 3 つのループからなるアクティビティのライフサイクルを監視できます: 
+</p> 
+
+<ul>
+<li>アクティビティの<b>ライフタイム全体</b>は、<code>{@link android.app.Activity#onCreate onCreate()}</code> が初めて呼び出されたときに始まり、最後に <code>{@link android.app.Activity#onDestroy}</code> が呼び出されたときに終了します。アクティビティは、{@code onCreate()} で「全体的」な状態のすべての初期設定を行い、{@code onDestroy()} 残っていたリソースをすべて解放します。たとえば、ネットワークからのデータのダウンロードをバックグラウンドで実行するスレッドは、{@code onCreate()} で作成され、{@code onDestroy()} で停止します。</li>
+
+<li><p>アクティビティの<b>可視ライフタイム</b>は、<code>{@link android.app.Activity#onStart onStart()}</code> の呼び出しで始まり、対応する <code>{@link android.app.Activity#onStop onStop()}</code> の呼び出しで終了します。このライフタイムの間は、ユーザーが画面上でそのアクティビティを見ることができます。ただし、アクティビティがフォアグラウンドにない場合や、ユーザーと対話していない場合もあります。これらの 2 つのメソッドの間は、ユーザーに対してアクティビティを表示するために必要なリソースを確保できます。たとえば、{@code onStart()} で {@link android.content.BroadcastReceiver} を登録して UI に影響する変化を監視し、表示しているアクティビティがユーザーから見えなくなったら {@code onStop()} で登録を解除できます。{@code onStart()} および {@code onStop()} メソッドは、アクティビティがユーザーから見え隠れするたびに繰り返し呼び出すことができます。</p></li>
+
+<li><p>アクティビティの<b>フォアグラウンド ライフタイム</b>は、<code>{@link android.app.Activity#onResume onResume()}</code> の呼び出しで始まり、対応する <code>{@link android.app.Activity#onPause onPause()}</code> の呼び出しで終了します。フォアグラウンド ランタイムの間は、このアクティビティが他のどのアクティビティよりも前面に表示され、ユーザーと対話しています。アクティビティは、一時停止状態と再開状態の間を頻繁に遷移します。たとえば、デバイスがスリープ状態になるときや新しいアクティビティを開始するときには {@code onPause()} が呼び出され、アクティビティの結果や新しいインテントが届いたときには {@code onResume()} が呼び出されます。したがって、これらのメソッドを記述する際は、できるだけ軽量化しておく必要があります。</p></li>
+</ul>
+
+<p>
+次の図に、これらのループとアクティビティの遷移経路を示します。色の付いた楕円は、アクティビティが取ることのできる主な状態です。長方形は、アクティビティが状態間を遷移するときに処理を実行するために実装できるコールバック メソッドを表します。
+<p>
+
+<p style="margin-left: 2em"><img src="{@docRoot}images/activity_lifecycle.png"
+alt="Android のアクティビティ ライフサイクルの状態遷移図"  /></p>  
+  
+<p>
+次の表では、各メソッドについて詳しく説明し、ライフサイクル全体における位置付けを示します:
+</p>
+
+<table border="2" width="85%" frame="hsides" rules="rows">
+<colgroup align="left" span="3"></colgroup>
+<colgroup align="left"></colgroup>
+<colgroup align="center"></colgroup>
+<colgroup align="center"></colgroup>
+
+<thead>
+<tr><th colspan="3">メソッド</th> <th>説明</th> <th>強制終了</th> <th>次</th></tr>
+</thead>
+
+<tbody>
+<tr>
+  <td colspan="3" align="left"><code>{@link android.app.Activity#onCreate onCreate()}</code></td>
+  <td>アクティビティが初めて作成されるときに呼び出されます。通常の静的な設定(ビューの作成、リストへのデータのバインドなど)は、すべてのこのメソッドで行う必要があります。このアクティビティの      以前の状態が保存されていた場合、このメソッドにはその状態を保持している Bundle オブジェクトが引数として(詳しくは、後述の<a href="#actstate">アクティビティの状態の保存</a>をご覧ください)。
+      <p>この後には、必ず {@code onStart()} が呼び出されます。</p></td>
+  <td align="center">不可</td>
+      <td align="center">{@code onStart()}</td>
+</tr>
+
+<tr>
+   <td rowspan="5" style="border-left: none; border-right: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
+   <td colspan="2" align="left"><code>{@link android.app.Activity#onRestart 
+onRestart()}</code></td>
+   <td>アクティビティが停止した後、それをもう一度開始する直前に呼び出されます。
+       <p>この後には、必ず {@code onStart()} が呼び出されます。</p></td>
+   <td align="center">不可</td>
+   <td align="center">{@code onStart()}</td>
+</tr>
+
+<tr>
+   <td colspan="2" align="left"><code>{@link android.app.Activity#onStart onStart()}</code></td>
+   <td>アクティビティがユーザーから見えるようになる直前に呼び出されます。
+       <p>その後、アクティビティがフォアグラウンドに表示された場合は {@code onResume()} が、他のアクティビティの後ろに隠れた場合は {@code onStop()} が呼び出されます。</p></td>
+    <td align="center">不可</td>
+    <td align="center">{@code onResume()} <br/>または<br/>{@code onStop()}</td>
+</tr>
+
+<tr>
+   <td rowspan="2" style="border-left: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
+   <td align="left"><code>{@link android.app.Activity#onResume onResume()}</code></td>
+   <td>アクティビティがユーザーとの対話を開始する直前に呼び出されます。この時点で、アクティビティはアクティビティ スタックの最上位にあり、ユーザーからの入力はこのアクティビティに対して行われます。
+       <p>この後には、必ず {@code onPause()} が呼び出されます。</p></td>
+   <td align="center">不可</td>
+   <td align="center">{@code onPause()}</td>
+</tr>
+
+<tr>
+   <td align="left"><code>{@link android.app.Activity#onPause onPause()}</code></td>
+   <td>システムが別のアクティビティを開始しようとしているときに呼び出されます。このメソッドは、保存されていない変更を永続データにコミットする場合や、アニメーションのように CPU を大量に消費する処理を停止する場合に使用するのが一般的です。このメソッドが終了するまでは次のアクティビティが開始されたないため、できる限り短時間で実行できるようにしておく必要があります。
+       <p>その後、アクティビティがフォアグラウンドに戻った場合は {@code onResume()} が、ユーザーから見えなくなった場合は {@code onStop()} が呼び出されます。</td>
+   <td align="center"><strong style="color:#800000">可能</strong></td>
+   <td align="center">{@code onResume()} <br/>または<br/>{@code onStop()}</td>
+</tr>
+
+<tr>
+   <td colspan="2" align="left"><code>{@link android.app.Activity#onStop onStop()}</code></td>
+   <td>アクティビティがユーザーから見えなくなったときに呼び出されます。見えなくなる状況としては、アクティビティが破棄された場合や、再開された別のアクティビティ(既存か新規かを問わず)によって隠された場合が考えられます。 
+       <p>その後、アクティビティがユーザーとの対話に戻った場合は {@code onRestart()} が、アクティビティが完全に終了する場合は {@code onDestroy()} が呼び出されます。</p></td>
+   <td align="center"><strong style="color:#800000">可能</strong></td>
+   <td align="center">{@code onRestart()} <br/>または<br/>{@code onDestroy()}</td>
+</tr>
+
+<tr>
+   <td colspan="3" align="left"><code>{@link android.app.Activity#onDestroy 
+onDestroy()}</code></td>
+   <td>アクティビティが破棄される前に呼び出されます。これが、アクティビティが受け取る最後の呼び出しとなります。このメソッドが呼び出される状況としては、アクティビティが完了する場合(<code>{@link android.app.Activity#finish 
+       finish()}</code> が呼び出されたとき)や、システムが領域を確保するために一時的にそのアクティビティのインスタンスを破棄する場合が考えられます。これらの 2 つの状況は、<code>{@link
+       android.app.Activity#isFinishing isFinishing()}</code> メソッドを使用して識別できます。</td>
+   <td align="center"><strong style="color:#800000">可能</strong></td>
+   <td align="center"><em>なし</em></td>
+</tr>
+</tbody>
+</table>
+
+<p>
+表の<b>強制終了</b>列に注目してください。この列は、メソッドが終了した後であれば、システムがアクティビティのコードの別の行を実行することなくいつでもアクティビティを実行しているプロセスを強制終了できるかどうかを示しています。<em></em>{@code onPause()}、{@code onStop()}、および {@code onDestroy()} メソッドの 3 つは「可能」となっています。1 番目に挙げた {@code onPause()} だけは、プロセスが強制終了する前に必ず呼び出されます。{@code onStop()} と {@code onDestroy()} は、必ず呼び出されるとは限りません。したがって、永続データ(たとえばユーザーによる編集)をストレージに書き込む際は {@code onPause()} を使用する必要があります。
+</p>
+
+<p>
+<b>強制終了</b>列が「不可」になっているメソッドは、それらが呼び出された瞬間から、アクティビティを実行しているプロセスを保護して強制終了されないようにします。したがって、アクティビティが強制終了可能な状態にあるのは、たとえば {@code onPause()} が返されてから {@code onResume()} が呼び出されるまでの間ということです。その後は、もう一度 {@code onPause()} が返されるまで、強制終了できる状態には戻りません。
+</p>
+
+<p>
+後述の<a href="#proclife">プロセスとライフサイクル</a>のセクションで詳しく説明しますが、ここでの定義で技術的には「強制終了可能」でないアクティビティでも、システムによって強制終了させられる可能性はありますが、他に利用できるリソースがないなど、極端に急を要する場合に限られます。
+</p>
+
+
+<h4 id="actstate">アクティビティの状態の保存</h4>
+
+<p>
+メモリ不足を補うためにユーザーではなくシステムがアクティビティを終了させた場合には,ユーザがそのアクティビティに戻ったときに、以前の状態のままであることを期待するでしょう。
+</p>
+
+<p>
+アクティビティが強制終了させられる前の状態を保存しておきたい場合は、アクティビティに <code>{@link android.app.Activity#onSaveInstanceState 
+onSaveInstanceState()}</code> メソッドを実装します。このメソッドは、アクティビティが破棄されやすい状態になる前(つまり {@code onPause()} が呼び出される前)に呼び出されます。その際、アクティビティの動的な状態を名前/値ペアとして記録できる {@link android.os.Bundle} オブジェクトが渡されます。アクティビティがもう一度開始されると、Bundle は {@code onCreate()} だけでなく、{@code onStart()} の後に呼び出される <code>{@link 
+android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}</code> メソッドにも渡され、保存されている状態をそのどちらかまたは両方で復元できます。
+</p>
+
+<p>
+{@code onSaveInstanceState()} および {@code onRestoreInstanceState()} メソッドは、これまでに説明した {@code onPause()} などとは異なり、ライフサイクル メソッドではありません。これらのメソッドは、常に呼び出されるわけではありません。たとえば、{@code onSaveInstanceState()} は、システムによってアクティビティが破棄しやすい状態にされる前には呼び出されますが、ユーザーのアクション(たとえば [[]戻る] キー)によってインスタンスが実際に破棄されるときには呼び出されません。そのような場合は、ユーザーがそのアクティビティに戻ることを想定する必要はないため、状態を保存する理由がないのです。
+</p>
+
+<p>
+{@code onSaveInstanceState()} は常に呼び出されるとは限らないため、アクティビティの一時的な状態を記録する目的のみに使用し、永続データの格納には使用しないようにしてください。この目的には {@code onPause()} を使用します。
+</p>
+
+
+<h4 id="coordact">アクティビティの協調</h4>
+
+<p>
+あるアクティビティが別のアクティビティを開始すると、両方のアクティビティのライフサイクル状態が遷移します。一方が一時停止または停止し、もう一方が開始されます。場合によっては、これらの協調させる必要があります。
+</p>
+
+<p>
+ライフサイクルのコールバックの順序は明確に定義されており、特に 2 つのアクティビティが同じプロセス内に存在する場合は次のようになります:
+</p>
+
+<ol>
+<li>現在のアクティビティの {@code onPause()} メソッドが呼び出されます。</li>
+
+<li>続いて、開始されるアクティビティの {@code onCreate()}、{@code onStart()}、および {@code onResume()} メソッドが順番に呼び出されます。</li>
+
+<li>その後、開始されたアクティビティが画面上で見えなくなると、その {@code onStop()} メソッドが呼び出されます。</li>
+</ol>
+
+
+<h3 id="servlife">サービスのライフサイクル</h3>
+
+<p>
+サービスは、以下の 2 つの方法で使用できます:
+</p>
+
+<ul>
+<li>いったん開始したら、停止させられる(または自ら停止する)まで実行し続けることができます。このモードでは、<code>{@link android.content.Context#startService Context.startService()}</code> が呼び出されて開始し、<code>{@link android.content.Context#stopService Context.stopService()}</code> 呼び出されて停止します。サービス自体が <code>{@link android.app.Service#stopSelf() Service.stopSelf()}</code> または <code>{@link android.app.Service#stopSelfResult Service.stopSelfResult()}</code> を呼び出して停止することもできます。サービスの開始時に {@code startService()} が何度呼び出されたとしても、{@code stopService()} を一度呼び出せばサービスは停止します。</li>
+
+<li><p>サービスで定義されているインターフェースをエクスポートし、これを介してプログラム的に操作できます。クライアントから Service オブジェクトへの接続を確立し、その接続を使用してサービスにアクセスします。接続は、<code>{@link android.content.Context#bindService Context.bindService()}</code> を呼び出して確立し、<code>{@link android.content.Context#unbindService Context.unbindService()}</code> でサービスを開始します。複数のクライアントが同じサービスにバインドすることも可能です。サービスがまだ開始されていなかった場合は,必要に応じて {@code bindService()} で開始できます。
+</p></li>
+</ul>
+
+<p>
+これら 2 つのモードは、完全に分離されているわけではありません。{@code startService()} で開始されたサービスにバインドすることも可能です。たとえば、再生する曲を指定した Intent オブジェクトで {@code startService()} を呼び出して音楽再生サービスを開始したとします。その後、たとえばユーザーがプレーヤーを操作したい場合や再生中の曲に関する情報を入手したい場合には、アクティビティから {@code bindService()} を呼び出してサービスとの接続を確立できます。このような場合、最後のバインドが閉じられるまでは、{@code stopService()} を呼び出してもサービスは停止しません。
+</p>
+
+<p>
+アクティビティと同様、サービスにもライフサイクル メソッドがあり、これらを実装することでサービスの状態の変化を監視できます。ただし、protected ではなく public で、以下の 3 つしかありません:
+</p>
+
+<p style="margin-left: 2em">{@code void onCreate()} <br/>{@code void onStart(Intent <i>intent</i>)} <br/>{@code void onDestroy()}</p>
+
+<p>
+これらのメソッドを実装することで、ネストされた 2 つのループからなるサービスのライフサイクルを監視できます:
+</p>
+
+<ul>
+<li>サービスの<b>ライフタイム全体</b>は、<code>{@link android.app.Service#onCreate onCreate()}</code> が呼び出されたときに始まり、<code>{@link android.app.Service#onDestroy}</code> 終了したときに終わります。アクティビティと同じく、サービスも {@code onCreate()} で初期設定を行い、{@code onDestroy()} で残っていたリソースをすべて解放します。たとえば、音楽再生サービスであれば、{@code onCreate()} で音楽を再生するスレッドを作成し、{@code onDestroy()} でそのスレッドを停止できます。</li>
+
+<li><p>サービスの<b>アクティブ ライフタイム</b>は、<code>{@link android.app.Service#onStart onStart()}</code> を呼び出したときに始まります。このメソッドには、{@code startService()} に渡された Intent オブジェクトが渡されます。音楽再生サービスは、この Intent オブジェクトをみて曲を見つけ、その再生を開始します。</p>
+
+<p>
+サービスの停止に相当するコールバック、つまり {@code onStop()} メソッドはありません。
+</p></li>
+</ul>
+
+<p>
+{@code onCreate()} および {@code onDestroy()} メソッドは、サービスを <code>{@link android.content.Context#startService Context.startService()}</code> または <code>{@link android.content.Context#bindService Context.bindService()}</code> のどちらで開始したかに関係なく、すべてのサービスで呼び出されます。一方、{@code onStart()} は、サービスを {@code startService()} で開始した場合のみ呼び出されます。
+</p>
+
+<p>
+サービスが他からのバインドを許可している場合は、以下のコールバック メソッドを追加で実装できます:
+</p>
+
+<p style="margin-left: 2em">{@code IBinder onBind(Intent <i>intent</i>)} <br/>{@code boolean onUnbind(Intent <i>intent</i>)} <br/>{@code void onRebind(Intent <i>intent</i>)}</p>
+
+<p>
+<code>{@link android.app.Service#onBind onBind()}</code> コールバックには {@code bindService()} に渡された Intent オブジェクトが渡され、<code>{@link android.app.Service#onUnbind onUnbind()}</code> には {@code unbindService()} 渡された Intent オブジェクトが渡されます。サービスがバインドを許可している場合は、クライアントがサービスと対話する通信チャネルを {@code onBind()} で返します。{@code onUnbind()} メソッドは、サービスに新しいクライアントが接続した場合に <code>{@link android.app.Service#onRebind onRebind()}</code> の呼び出しを要求できます。
+</p>
+
+<p>
+次の図に、サービスのコールバック メソッドを示します。なお、{@code startService()} で作成されたサービスと、{@code bindService()} で作成されたサービスを分けて記述していますが、作成された方法に関係なく,すべてのサービスはクライアントからのバインドを許可できます。したがって、どのサービスも {@code onBind()} および{@code onUnbind()} メソッドの呼び出しを受け取る可能性はあります。
+</p>
+
+<p style="margin-left: 2em"><img src="{@docRoot}images/service_lifecycle.png"
+alt="サービス コールバックの状態遷移図"  /></p>
+
+
+<h3 id="broadlife">ブロードキャスト レシーバのライフサイクル</h3>
+
+<p>
+ブロードキャスト レシーバのコールバック メソッドは次の 1 つのみです:
+</p>
+
+<p style="margin-left: 2em">{@code void onReceive(Context <i>curContext</i>, Intent <i>broadcastMsg</i>)}</p>
+
+<p>
+レシーバにブロードキャスト メッセージが届くと、<code>{@link android.content.BroadcastReceiver#onReceive onReceive()}</code> メソッドが呼び出され、メッセージを保持する Intent オブジェクトが渡されます。ブロードキャスト レシーバは、このメソッドの実行中のみアクティブと見なされます。{@code onReceive()} 終了すると、ブロードキャスト レシーバはアクティブでなくなります。
+</p>
+
+<p>
+ブロードキャスト レシーバがアクティブになっているプロセスは、強制終了しないよう保護されます。一方、アクティブでないコンポーネントのみからなるプロセスは、それが消費しているメモリが他のプロセスで必要になった場合は、いつでも強制終了される可能性があります。
+</p>
+
+<p>
+この点は、ブロードキャスト メッセージへの応答に時間がかかるため、ユーザー インターフェースの他のコンポーネントを実行しているメイン スレッドとは別のスレッドで何らかの処理を行う必要がある場合に問題になります。{@code onReceive()} が新しいスレッドを生成して終了した場合、プロセス内に他にアクティブなアプリケーション コンポーネントがなければ、そのスレッドを含めたプロセス全体がアクティブでないと判断されて強制終了させられるおそれがあります。この問題を回避するには、{@code onReceive()} でサービスを開始し、そのサービスにジョブを実行させます。これにより、プロセス内にまだアクティブなコンポーネントがあると見なされます。
+</p>
+
+<p>
+次のセクションでは、プロセスが強制終了される可能性が高くなる状況についてさらに詳しく説明します。
+</p>
+
+
+<h3 id="proclife">プロセスとライフサイクル</h3>
+
+<p>Android は、プロセスをできるだけ長い間維持しようとします。しかし、最終的にメモリが不足したときには、古いプロセスを削除しなければならなくなります。Android では、どのプロセスを維持し、どのプロセスを強制終了させるかを判断するため、プロセス内で実行されているコンポーネントと各コンポーネントの状態に基づいて、各プロセスを「重要度の階層」の位置づけます。まず最も重要度の低いプロセスが削除され、次は 2 番目に重要度の低いプロセス、その次に 3 番目、というように判断されます。階層は 5 つのレベルで構成されます。以下では、重要度の高いものから順に説明します:
+</p>
+
+<ol>
+
+<li><b>フォアグラウンド プロセス</b>は、ユーザーがその時点で行っている作業に必要なプロセスです。以下のいずれかの条件を満たしているプロセスは、フォアグラウンド プロセスと見なされます:
+
+<ul>
+<li>ユーザーと対話中のアクティビティを実行している(Activity オブジェクトの <code>{@link android.app.Activity#onResume 
+onResume()}</code> メソッドが呼び出されている)。</li>
+
+<li><p>ユーザーと対話中のアクティビティにバインドされているサービスを実行している。</p></li>
+
+<li><p>いずれかのライフサイクル コールバック(<code>{@link android.app.Service#onCreate 
+onCreate()}</code>、<code>{@link android.app.Service#onStart onStart()}</code>、または <code>{@link android.app.Service#onDestroy onDestroy()}</code>)を実行している {@link android.app.Service} オブジェクトを保持している。</p></li>
+
+<li><p><code>{@link android.content.BroadcastReceiver#onReceive 
+onReceive()}</code> メソッドを実行している {@link android.content.BroadcastReceiver} オブジェクトを保持している。</p></li>
+</ul>
+
+<p>
+同時に存在するフォアグラウンド プロセスは少数に限られています。フォアグラウンド プロセスは、メモリが極端に不足し、すべてのフォアグラウンド プロセスの実行を継続できない場合の最終手段として強制終了させられます。通常、その時点でデバイスはメモリ ページングの状態に達しており、ユーザー インターフェースを応答可能な状態に維持するためには、フォアグラウンド プロセスの一部を強制終了させなければならない状況に陥っています。
+</p></li>
+
+<li><p><b>可視プロセス</b>は、フォアグラウンド コンポーネントではないものの、ユーザーが見ている画面に影響を及ぼすことのできるプロセスです。以下のいずれかの条件を満たしているプロセスは、可視プロセスと見なされます:</p>
+
+<ul>
+<li>フォアグラウンドではないがユーザーから見ることができるアクティビティを実行している(その <code>{@link android.app.Activity#onPause onPause()}</code> メソッドが呼び出されている)。これは、たとえばフォアグラウンド アクティビティがダイアログで、その背後に直前のアクティビティが見えるような状況です。</li>
+
+<li><p>ユーザーから見ることのできるアクティビティにバインドされているサービスを実行している。</p></li>
+</ul>
+
+<p>
+可視プロセスは、非常に重要なプロセスと見なされ、すべてのフォアグラウンド プロセスの実行を維持するために必要でない限り、強制終了させられることはありません。
+</p></li>
+
+<li><p><b>サービス プロセス</b>は、<code>{@link android.content.Context#startService startService()}</code> メソッドで開始されたサービスを実行しているプロセスのうち、より重要度の高い 2 つのレベルのどちらにも該当しないプロセスです。サービス プロセスは、ユーザーに見えるものとの直接的な関係はありませんが、たとえばバックグラウンドでの MP3 の再生、ネットワークからのデータのダウンロードなど、ユーザーが気にかけている処理であることが一般的です。したがって、すべてのフォアグラウンド プロセスと可視プロセスに加え、これらのサービス プロセスの実行を維持するだけのメモリが確保できる限り、強制終了させられることはありません。  
+</p></li>
+
+<li><p><b>バックグラウンド プロセス</b>は、その時点でユーザーから見えないアクティビティを保持している(Activity オブジェクトの <code>{@link android.app.Activity#onStop onStop()}</code> メソッドが呼び出されている)プロセスです。これらのプロセスは、ユーザー エクスペリエンスに直接的には影響しておらず、フォアグラウンド、可視、サービス プロセスからメモリが要求された場合はいつでも強制終了する可能性があります。通常は数多くのバックグラウンド プロセスが実行されているため、それらを LRU(least recently used)リストに登録し、ユーザーが一番最近見たアクティビティのプロセスが最後に強制終了するような仕組みになっています。アクティビティにライフサイクル メソッドが正しく実装されており、現在の状態が正しく保存されていれば、プロセスを強制終了してもユーザー エクスペリエンスに悪影響が及ぶことはありません。 
+</p></li>
+
+<li><p><b>空のプロセス</b>は、アクティブなアプリケーション コンポーネントを保持していないプロセスです。このようなプロセスを維持しておく唯一の理由は、これをキャッシュとして使用し、次回コンポーネントを実行するときの起動時間を短くするためです。多くの場合、システムはこれらのプロセスを強制終了させて、プロセス キャッシュとその基礎となるカーネル キャッシュの間でシステム リソース全体のバランスを取ります。</p></li>
+
+</ol>
+
+<p>
+各プロセスは、その時点でアクティブなコンポーネントの重要度に基づいて、そのプロセスが取りうる最も高いレベルにランク付けされます。たとえば、あるプロセスがサービスと可視アクティビティをホストしている場合、そのプロセスはサービス プロセスではなく可視プロセスとしてランク付けされます。
+</p>
+
+<p>
+また、あるプロセスに他のプロセスが依存しているために、そのプロセスのランクが引き上げられる可能性もあります。他のプロセスから依存されているプロセスが、依存しているプロセスよりも低いレベルにランク付けされることはありません。たとえば、プロセス A 内のコンテンツ プロバイダにプロセス B 内のクライアントが依存している場合や、プロセス A 内のサービスがプロセス B 内のコンポーネントにバインドされている場合、プロセス A は常にプロセス B よりは重要度が高いと見なされます。
+</p> 
+
+<p>
+サービスを実行しているプロセスは、バックグラウンド アクティビティを実行しているプロセスよりも高くランク付けされます。したがって、時間のかかる処理を実行する場合、特にその処理がアクティビティよりも長く続くような場合は、単にスレッドを生成するのではなく、その処理用のサービスを開始することをおすすめします。たとえば、バックグラウンドで音楽を再生する場合や、カメラで撮影した写真を Web サイトにアップロードする場合などはこれに当たります。サービスを使用することで、アクティビティがどのような状況にあっても、処理の重要度として「サービス プロセス」レベル以上を維持できます。<a href="#broadlife">ブロードキャスト レシーバのライフサイクル</a>のセクションでも説明しましたが、ブロードキャスト レシーバにおいてもこれと同じ理由で、処理に時間がかかる場合はスレッドではなくサービスを使用することをおすすめします。
+</p>
diff --git a/docs/html/intl/ja/guide/tutorials/hello-world.jd b/docs/html/intl/ja/guide/tutorials/hello-world.jd
new file mode 100644
index 0000000..31857ce
--- /dev/null
+++ b/docs/html/intl/ja/guide/tutorials/hello-world.jd
@@ -0,0 +1,375 @@
+page.title=Hello, World
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+    <h2>このドキュメントの内容</h2>
+    <ol>
+      <li><a href="#avd">AVD の作成</a></li>
+      <li><a href="#create">プロジェクトを作成する</a></li>
+      <li><a href="#ui">UI を構築する</a></li>
+      <li><a href="#run">コードを実行する</a></li>
+      <li><a href="#upgrading">UI を XML レイアウトにアップグレードする</a></li>
+      <li><a href="#debugging">プロジェクトをデバッグする</a></li>
+      <li><a href="#noeclipse">Eclipse を使用せずにプロジェクトを作成する</a></li>
+    </ol>
+  </div>
+</div>
+
+<p>デベロッパーにとって、開発フレームワークの第一印象は、どれだけ簡単に「Hello, World」を記述できるかで決まります。Android では、非常に簡単に記述できます。総合開発環境として Eclipse を使用している場合には、開発は特に簡単です。プロジェクトの作成と管理に使用できる便利なプラグインが用意されており、開発サイクルを大幅にスピードアップできるためです。</p>
+
+<p>Eclipse を使用していない場合でも問題ありません。<a href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>に慣れてから、このチュートリアルに戻り、Eclipse に関する部分以外を参考にしてください。</p>
+
+<p>開始する前に、最新の SDK がインストールされている必要があります。また、Eclipse を使用する場合には、ADT プラグインもインストールされている必要があります。これらのプログラムがインストールされていない場合は、「<a href="{@docRoot}sdk/{@sdkCurrent}/installing.html">Installing the Android SDK</a>」を参考にインストールを実行して、完了後にこのチュートリアルに戻ってください。</p>
+
+<h2 id="avd">AVD の作成</h2>
+
+<div class="sidebox-wrapper">
+  <div class="sidebox-inner">
+    <p>AVD の使用方法と使用可能なオプションについて詳しくは、<a href="{@docRoot}guide/developing/tools/avd.html">Android 仮想デバイス</a> のドキュメントを参照してください。</p>
+  </div>
+</div>
+
+<p>このチュートリアルでは、開発したアプリケーションを Android エミュレータで実行します。エミュレータを起動するには、事前に Android 仮想デバイス(AVD)を作成する必要があります。AVD は、エミュレータが使用するシステム イメージとデバイスの設定を定義するものです。</p>
+
+<p>AVD を作成するには、Android SDK に含まれている「android」ツールを使用します。コマンド プロンプトまたはターミナルを開き、SDK パッケージの中の <code>tools/</code> ディレクトリに移動して、次のコマンドを実行します。
+<pre>
+android create avd --target 2 --name my_avd
+</pre>
+
+<p>カスタム ハードウェア プロファイルを作成するかどうかを尋ねられます。ここではひとまず、リターン キーを押してスキップします(デフォルトの回答は「No」となっています)以上で AVD の作成は終了です。この作業により、Android 1.5 プラットフォームを使用する「my_avd」という名前の AVD が構成されました。これで、AVD をエミュレータで使用できる状態になりました。</p>
+
+<p>上記のコマンドで使用した <code>--target</code> オプションは、エミュレータを実行する配備ターゲットを指定するもので、必須オプションです。<code>--name</code> オプションは新規 AVD の名前を定義するもので、これも必須オプションです。</p>
+
+
+<h2 id="create">新規 Android プロジェクトを作成する</h2>
+
+<p>AVD を作成したら、次は Eclipse 内で新規 Android プロジェクトを開始します。</p>
+
+<ol>
+    <li>Eclipse で、<strong>[[]ファイル(File)] &gt; [[]新規(New)] &gt; [[]プロジェクト(Project)]</strong> を選択します。 
+      <p>ADT Plugin for Eclipse が正常にインストールされていれば、表示されるダイアログに、「Android」というラベルの付いたフォルダと、その中の「Android プロジェクト(Android Project)」が表示されます(1 つまたは複数の Android プロジェクトを作成した後は、「Android XML File」というエントリも表示されるようになります)。</p>
+    </li>
+
+    <li>「Android プロジェクト(Android Project)」を選択して、[[]<strong>次へ(Next)</strong>] をクリックします。<br/><a href="images/hello_world_0.png"><img src="images/hello_world_0.png" style="height:230px" alt=""  /></a>
+    </li>
+
+    <li>プロジェクトの詳細項目に以下の値を入力します。
+        <ul>
+          <li><em>プロジェクト名(Project name):</em> HelloAndroid</li>
+          <li><em>アプリケーション名(Application name):</em> Hello, Android</li>
+          <li><em>パッケージ名(Package name):</em> com.example.helloandroid(または自分のプライベート ネームスペース)</li>
+          <li><em>アクティビティを作成(Create Activity):</em> HelloAndroid</li>
+          <li><em>SDK の最小バージョン(Min SDK Version):</em> 2</li>
+        </ul>
+        <p>[[]<strong>完了(Finish)</strong>] をクリックします。</p>
+
+        <a href="images/hello_world_1.png"><img src="images/hello_world_1.png" style="height:230px" alt=""  /></a>
+
+        <p>各フィールドの説明は以下のとおりです。</p>
+      
+        <dl>
+            <dt><em>プロジェクト名(Project Name)</em></dt>
+                <dd>Eclipse のプロジェクト名。プロジェクト ファイルを格納するディレクトリの名前です。</dd>
+            <dt><em>アプリケーション名(Application Name)</em></dt>
+                <dd>アプリケーション名はユーザーにわかりやすいアプリケーションのタイトルにします。この名前が Android 携帯端末に表示されます。</dd>
+            <dt><em>パッケージ名(Package Name)</em></dt>
+                <dd>作成したすべてのソース コードを格納するパッケージ ネームスペースです(Java プログラミング言語で作成するパッケージと同じルールに従います)。また、これにより、スタブ Activity が生成されるパッケージの名前も設定されます。
+                  <p>パッケージ名は Android システムにインストールされたすべてのパッケージに共通して固有のものでなければなりません。このため、作成するアプリケーションに標準的なドメイン スタイルのパッケージを使用することが非常に重要です。上記の例では、「com.example」というネームスペースを使用しています。これはサンプル ドキュメント用のネームスペースです。実際にアプリケーションを作成する際には、所属する組織または法人に適切なネームスペースを使用します。</p></dd>
+            <dt><em>アクティビティを作成(Create Activity)</em></dt>
+                <dd>プラグインによって生成されるクラス スタブの名前です。クラス スタブは Android の {@link android.app.Activity} クラスのサブクラスとなります。アクティビティとは単に、実行して何らかの処理を行うことができるクラスを意味します。選択に応じて UI を作成することもできます(ただし必須ではありません)。チェックボックスになっていることからわかるように、これは任意選択の項目です。しかし、実際にはほとんどのアプリケーションでは、アクティビティをアプリケーションの基盤として使用しています。</dd>
+            <dt><em>SDK の最小バージョン(Min SDK Version)</em></dt>
+                <dd>作成するアプリケーションが必要とする最小 API レベルを指定する値です。ここに入力した API レベルが、選択可能なターゲットのいずれかで提供される API レベルと一致する場合は、ビルド ターゲットが自動的に選択されます(この例では、API レベルに「2」と入力するとターゲット Android 1.1 が選択されます)。Android システム イメージと Android SDK それぞれの新しいバージョンでは、API に追加または変更が加えられている可能性があります。追加または変更が加えられている場合、新しい API レベルがシステム イメージに割り当てられ、どのアプリケーションの実行を許可するかが規制されます。アプリケーションで必要な API レベルがデバイスでサポートされるレベルよりも<em>高い</em>場合、アプリケーションはインストールされません。</dd>
+        </dl>
+      
+        <p><em>その他のフィールド</em>: 「デフォルト ロケーションの使用」チェックボックスでは、プロジェクトのファイルが生成され保存されるディスク上の場所を変更することができます。「ビルド ターゲット」は、作成するアプリケーションがコンパイルされるときにターゲットとするプラットフォームです(この項目は [[]SDK の最小バージョン(Min SDK Version)] の入力値に基づいて自動的に選択されます)。</p>
+
+        <p class="note">ここで、選択した「ビルド ターゲット」で Android 1.1 プラットフォームが使用されることに注目してください。これは、作成するアプリケーションが Android 1.1 プラットフォーム ライブラリをターゲットとしてコンパイルされることを意味します。先ほど作成した AVD は Android 1.5 プラットフォームで実行されます。バージョンの数字が一致しませんが、Android アプリケーションには上方互換性があるため、1.1 プラットフォーム ライブラリをターゲットとして構築されたアプリケーションでも 1.5 プラットフォームで正常に動作します。ただしその逆の場合は正常に動作しません。</p>
+    </li>
+</ol>
+
+<p>さて、これで Android プロジェクトを使用できる状態になりました。プロジェクトは左側のパッケージ エクスプローラー(Package Explorer)で表示できます。<em>「HelloAndroid」 &gt; 「src」 &gt; 「com.example.helloandroid」</em> の中にある <code>HelloAndroid.java</code> ファイルを開きます。ファイルの内容は次のようになっています。</p>
+
+<pre>
+package com.example.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HelloAndroid extends Activity {
+    /** Called when the activity is first created. */
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+}</pre>
+
+<p>クラスが {@link android.app.Activity} クラスに基づいていることに注目してください。アクティビティ(Activity)とは、処理を実行するために使用される単体のアプリケーション エンティティです。1 つのアプリケーションにはいくつものアクティビティが含まれる場合がありますが、ユーザーが一度に操作するのは 1 つのアクティビティです。アクティビティが開始すると、Android システムによって {@link android.app.Activity#onCreate(Bundle) onCreate()} メソッドが呼び出されます。このタイミングですべての初期化と UI セットアップを実行します。アクティビティにユーザー インターフェースは必須ではありませんが、通常はユーザー インターフェースを装備します。</p>
+
+<p>では、コードを変更してみましょう。 </p>
+
+
+<h2 id="ui">UI を構築する</h2>
+
+<p>下記の変更済みのコードを参照して、お手元の HelloAndroid クラスに同じ変更を加えてみてください。太字の部分が追加された行です。</p>
+
+<pre>
+package com.android.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+<strong>import android.widget.TextView;</strong>
+
+public class HelloAndroid extends Activity {
+   /** Called when the activity is first created. */
+   &#64;Override
+   public void onCreate(Bundle savedInstanceState) {
+       super.onCreate(savedInstanceState);
+       <strong>TextView tv = new TextView(this);
+       tv.setText(&quot;Hello, Android&quot;);
+       setContentView(tv);</strong>
+   }
+}</pre>
+
+<p class="note"><strong>ヒント:</strong> プロジェクトにインポート パッケージを簡単に追加できる方法として、<strong>Ctrl+Shift+O</strong>(Mac では <strong>コマンド+Shift+O</strong>)を押す方法があります。これは、コードの記述に基づいて足りないパッケージを特定して追加する Eclipse のショートカット キーです。</p>
+
+<p>Android のユーザー インターフェースは、「ビュー(Views)」と呼ばれるオブジェクトの階層で構成されています。{@link android.view.View} は、UI レイアウト内でボタン、画像、または(このサンプルのように)テキスト ラベルといった要素として使用される、描画可能なオブジェクトです。これらのオブジェクトのそれぞれが View クラスのサブクラスであり、テキストを処理するサブクラスは {@link android.widget.TextView} です。</p>
+
+<p>この変更では、クラス コンストラクタを使用して TextView を作成します。このクラス コンストラクタは、パラメータとして Android {@link android.content.Context} インスタンスを受け入れます。Context とは、システムへのハンドルであり、リソースの解決、データベースや設定へのアクセスの取得などのサービスを提供します。Activity クラスは Context を継承します。作成する HelloAndroid クラスは、Activity のサブクラスであるため、Context でもあります。したがって、<code>this</code> を Context 参照として TextView に引き渡すことができます。</p>
+
+<p>次に、{@link android.widget.TextView setText(CharSequence) setText()} を使用してテキスト コンテンツを定義します。</p>
+
+<p>最後に、そのコンテンツが Activity UI のコンテンツとして表示されるように、TextView を {@link android.app.Activity#setContentView(View) setContentView()} に引き渡します。Activity によってこのメソッドが呼び出されなければ、UI は表示されず、空白の画面が表示されます。</p>
+
+<p>これで、Android で「Hello, World」が表示されるようになりました。次の手順はもちろん、アプリケーションの実行です。</p>
+
+
+<h2 id="run">アプリケーションを実行する</h2>
+
+<p>Eclipse プラグインでは、非常に簡単にアプリケーションを実行できます。</p>
+
+<ol>
+  <li><strong>[[]実行] &gt; [[]実行]</strong> を選択します。</li>
+  <li>「Android Application」を選択します。</li>
+</ol>
+
+<div class="sidebox-wrapper">
+  <div class="sidebox-inner">
+    <p>Eclipse での起動構成の作成と編集について詳しくは、「<a href="{@docRoot}guide/developing/eclipse-adt.html#RunConfig">ADT を使用した Eclipse での開発</a>」を参照してください。</p>
+  </div>
+</div>
+
+<p>Eclipse ADT によって自動的にプロジェクトの新規起動構成が作成され、Android エミュレータが自動的に起動します。エミュレータが起動した後、少し経つとアプリケーションが表示されます。次のような画面が表示されます。</p>
+
+  <a href="images/hello_world_5.png"><img src="images/hello_world_5.png" style="height:230px" alt=""  /></a>
+
+<p>グレーのバーに表示されている「Hello, Android」は、アプリケーションのタイトルです。このタイトルは Eclipse プラグインによって自動的に作成されます(文字列は <code>res/values/strings.xml</code> ファイル内で定義され、<code>AndroidManifest.xml</code> によって参照されます)。タイトルの下のテキストは、先ほど TextView オブジェクトで作成した実際のテキストです。</p>
+
+<p>これで「Hello World」についての基本的なチュートリアルは終了ですが、この続きもぜひ読んでください。Android アプリケーションの開発に関するさらに有益な情報を紹介しています。</p>
+
+
+<h2 id="upgrading">UI を XML レイアウトにアップグレードする</h2>
+
+<p>先ほど作成した「Hello, World」のサンプルは、「プログラマティック」と呼ばれる UI レイアウトを使用しています。「プログラマティック」とは、アプリケーションの UI を直接ソース コードで作成および構築することを意味します。UI プログラミングの経験が豊富な方であればおそらく、このようなアプローチが時にいかに脆弱になり得るかをよくご存じでしょう。レイアウトの軽微な変更のたびに、ソース コード全体に関わる大きな問題が発生する可能性があるからです。また、複数のビューを適切に結びつけることも忘れられがちであるため、これによりレイアウトにエラーが発生し、コードのデバッグで時間が無駄になる場合があります。</p>
+
+<p>その理由から、Android では、XML ベースのレイアウト ファイルを使用する別の UI 構築モデルを用意しています。この概念を簡単に説明するには、サンプルを紹介するのが一番です。ここに示すのは、上記の「プログラマティック」に構築したサンプルと同じように動作する XML レイアウト ファイルです。</p>
+
+<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;TextView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+  android:layout_width=&quot;fill_parent&quot;
+  android:layout_height=&quot;fill_parent&quot;
+  android:text=&quot;@string/hello&quot;/&gt;</pre>
+
+<p>Android XML レイアウト ファイルの全般的な構造はシンプルです。XML 要素がツリー構造になっており、含まれた各ノードが View クラスの名前を表しています(このサンプルでは View 要素が 1 つのみですが)。XML レイアウト内の要素として、{@link android.view.View} を拡張する任意のクラスの名前を使用できます。これには作成するコードの中で定義するカスタム View クラスも含まれます。この構造により、プログラマティックなレイアウトよりもシンプルな構造と構文を使用して、迅速な UI 構築を非常に簡単に行うことができます。このモデルは、アプリケーションの表示(つまり UI)を、データの取得と入力に使用されるアプリケーション ロジックから切り離すことができる Web 開発モデルからヒントを得て考案されました。</p>
+
+<p>上記の XML サンプルには、<code>TextView</code> という View 要素 1 つのみが含まれています。この要素は 4 つの XML 属性を持っています。下表に、これらの 4 つの属性の説明をまとめました。</p>
+
+<table>
+    <tbody>
+        <tr>
+            <th>
+                属性
+            </th>
+            <th>
+                説明
+            </th>
+        </tr>
+        <tr>
+            <td>
+                <code>xmlns:android</code>
+            </td>
+            <td>
+                Android ネームスペースで定義された共通の属性を参照することを Android ツールに伝える XML ネームスペース宣言です。すべての Android レイアウト ファイル内の最初と最後のタグはこの属性を持つ必要があります。<br>
+            </td>
+        </tr>
+        <tr>
+            <td>
+                <code>android:layout_width</code>
+            </td>
+            <td>
+                該当の View が画面の利用可能な幅のうちどれくらいを占めるかを定義します。このサンプルでは、この View しかないため、「fill_parent」という値を使用して画面全体を占めることにします。<br>
+            </td>
+        </tr>
+        <tr>
+            <td>
+                <code>android:layout_height</code>
+            </td>
+            <td>
+                android:layout_width とよく似た属性で、幅ではなく高さを表します。
+            </td>
+        </tr>
+        <tr>
+            <td>
+                <code>android:text</code>
+            </td>
+            <td>
+                TextView が表示するテキストを設定します。このサンプルでは、ハードコード記述された文字列値ではなく文字列リソースを使用します。文字列「<em>hello</em>」は <em>res/values/strings.xml</em> ファイル内で定義されます。アプリケーションに文字列を挿入する場合にはこの方法が推奨されます。レイアウト ファイルのハードコードを直接変更する必要がないため、アプリケーションの他の言語へのローカライズがスムーズに進むからです。詳しくは、「<a href="{@docRoot}guide/topics/resources/resources-i18n.html">リソースと国際化</a>」を参照してください。
+            </td>
+        </tr>
+    </tbody>
+</table>
+
+
+<p>これらの XML レイアウト ファイルは、作成するプロジェクトの <code>res/layout/</code> ディレクトリ内に置かれます。「res」は「resources」の略で、アプリケーションに必要なコード以外のすべてのアセットがこのディレクトリに格納されます。リソースには、レイアウト ファイルの他に、画像、音声、ローカライズされた文字列などのアセットがあります。</p>
+
+<div class="sidebox">
+  <h2>横表示レイアウト</h2>
+  <p>横表示の場合に異なるデザインで表示するには、レイアウト XML ファイルを /res/layout-land 内に入れます。Android 端末のレイアウトが横表示に変わると自動的にこのディレクトリが参照されます。このように横表示向けに定義されたレイアウトが存在しない場合、自動的にデフォルトのレイアウトが拡大して使用されます。</p>
+</div>
+
+<p>Eclipse プラグインでは、このようなレイアウト ファイルの 1 つである「main.xml」が自動的に作成されます。先ほど「Hello World」アプリケーションを作成した際には、このファイルは無視してプログラマティックにレイアウトを作成しました。この作成方法は Android フレームワークについてより深く理解していただくことを意図したもので、実際にはほとんどの場合レイアウトはコードではなく XML ファイルで定義します。以下の手順では、既存のアプリケーションを変更して XML レイアウトが使用されるようにする方法を説明します。</p>
+
+<ol>
+  <li>Eclipse のパッケージ エクスプローラー(Package Explorer)で、<code>/res/layout/</code> フォルダを展開し、<code>main.xml</code> を開きます(開いた後、場合によっては XML ソースを見るのにウィンドウ下部にある「main.xml」タブをクリックする必要があります)。ファイルの内容を以下の XML に置き換えます。
+
+<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;TextView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+  android:layout_width=&quot;fill_parent&quot;
+  android:layout_height=&quot;fill_parent&quot;
+  android:text=&quot;@string/hello&quot;/&gt;</pre>
+<p>ファイルを保存します。</p>
+</li>
+
+<li><code>res/values/</code> フォルダ内の <code>strings.xml</code> を開きます。このファイルは、作成するユーザー インターフェースのためのすべてのデフォルトのテキスト文字列を保存するものです。Eclipse を使用している場合、ADT によってあらかじめ <em>hello</em> と <em>app_name</em> という 2 つの文字列が用意された状態になります。<em>hello</em> を何か別の文字列に書き換えてみましょう。たとえば「Hello, Android! I am a string resource!」としてみましょう。変更後のファイルの全体は次のようになります。
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+    &lt;string name="hello">Hello, Android! I am a string resource!&lt;/string>
+    &lt;string name="app_name">Hello, Android&lt;/string>
+&lt;/resources>
+</pre>
+</li>
+
+<li>次に、<code>HelloAndroid</code> クラスを開いて、XML レイアウトを使用して変更します。ファイルを編集して次のような内容にします。
+<pre>
+package com.example.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HelloAndroid extends Activity {
+    /** Called when the activity is first created. */
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+}</pre>
+
+<p>この変更を行う際に、コードを手入力してコード補完機能を試してみましょう。「R.layout.main」と入力しようとすると、プラグインによって入力候補が表示されます。この機能の便利さは、開発中に何回も実感すると思います。</p>
+
+<p>View オブジェクトに <code>setContentView()</code> を引き渡す代わりに、レイアウト リソースへの参照を付与します。リソースは <code>R.layout.main</code> として識別されます。これは、<code>/res/layout/main.xml</code> で定義されたレイアウトを、コンパイルされたオブジェクトで表したものです。Eclipse プラグインでは、この参照がプロジェクトの R.java クラス内に自動的に作成されます。Eclipse を使用していない場合、Ant を実行してアプリケーションのビルドを行う際に R.java クラスが生成されます(R クラスについて詳しくは後ほど説明します)。</p>
+</li>
+</ol>
+
+<p>ここで、アプリケーションを再実行します。起動構成は作成済みであるため、ここでは緑色の矢印アイコンをクリックして実行するか、または <strong>[[]実行(Run)] &gt; [[]ヒストリーの実行(Run History)] &gt; [[]Android Activity]</strong> を選択するだけです。TextView 文字列に加えた変更を除けば、アプリケーションは同じに見えます。ここでポイントとなるのは、2 つの異なるレイアウト編集方法を使用して同じ結果が得られるということです。</p>
+
+<p class="note"><strong>ヒント:</strong> ショートカット キー<strong>Ctrl+F11</strong>(Mac では <strong>コマンド+Shift+F11</strong>)を使用して、現在表示されているアプリケーションを実行することができます。</p>
+
+<p>ここからは、デバッグの基礎知識と、他の総合開発環境に関する補足情報について説明します。さらに詳しく学習したい場合は、「<a href="{@docRoot}guide/topics/fundamentals.html">アプリケーションの基礎</a>」を参照してください。Android アプリケーションが動作するためのすべての要素について説明しています。また、「<a href="{@docRoot}guide/index.html">デベロッパー ガイド</a>」の導入ページを参照して、<em>デベロッパー ガイド</em> ドキュメントの概要を確認してください。</p>
+
+
+<div class="special">
+<h3>R クラス</h3>
+<p>Eclipse で、<code>R.java</code> という名前のファイル(<code>gen/</code>(「生成された Java ファイル(Generated Java Files)」フォルダ内)を開きます。ファイルの内容は次のようになっています。</p>
+
+<pre>
+package com.example.helloandroid;
+
+public final class R {
+    public static final class attr {
+    }
+    public static final class drawable {
+        public static final int icon=0x7f020000;
+    }
+    public static final class layout {
+        public static final int main=0x7f030000;
+    }
+    public static final class string {
+        public static final int app_name=0x7f040001;
+        public static final int hello=0x7f040000;
+    }
+}
+</pre>
+
+<p>プロジェクトの <code>R.java</code> ファイルは、ファイル内で定義されたすべてのリソースへのインデックスです。ソース コード内では、プロジェクトに含めたすべてのリソースを参照するための簡略形式としてこのクラスを使用します。これは、Eclipse などの総合開発環境のコード補完機能とともに使用すると特に便利です。探している特定の参照をすばやくインタラクティブに見つけることができるからです。</p>
+
+<p>お手元のファイルはこれとは若干異なる可能性があります(おそらく 16 進値が異なるためです)。ここでは、「layout」という名前の内部クラスと、そのメンバーであるフィールド「main」に注目します。Eclipse プラグインにより main.xml という名前の XML レイアウト ファイルが認識され、ここにそのためのクラスが生成されたものです。プロジェクトに他のリソース(<code>res/values/string.xml</code> ファイル内の文字列や <code>res/drawable/</code> ディレクトリ内の描画可能オブジェクトなど)を追加すると、<code>R.java</code> に最新の変更が反映されます。</p>
+<p>Eclipse を使用していない場合は、(Ant ツールを使用した)ビルド時にこのクラス ファイルが生成されます。</p>
+<p><em>くれぐれもこのファイルを手動で編集しないようにしてください。</em></p>
+</div>
+
+<h2 id="debugging">プロジェクトをデバッグする</h2>
+
+<p>Android Plugin for Eclipse は、Eclipse のデバッガと優れた連動性を発揮します。このメリットを確認するため、作成したコードにバグを埋め込んでみましょう。作成した HelloAndroid ソース コードを次のように変更します。</p>
+
+<pre>
+package com.android.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HelloAndroid extends Activity {
+    /** Called when the activity is first created. */
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Object o = null;
+        o.toString();
+        setContentView(R.layout.main);
+    }
+}</pre>
+
+<p>この変更は、単にコードに NullPointerException を発生させるものです。アプリケーションを再度実行すると、最終的に次のような画面が表示されます。</p>
+
+  <a href="images/hello_world_8.png"><img src="images/hello_world_8.png" style="height:230px" alt=""  /></a>
+
+<p>「強制終了」を押してアプリケーションを終了し、エミュレータ ウィンドウを閉じます。</p>
+
+<p>エラーの詳細を確認するには、ソース コード内の <code>Object o = null;</code> 行にブレークポイントを設定します(該当するソース コード行の横にあるマーカー バーをダブルクリックします)。次に、メニューから <strong>[[]実行(Run)] &gt; [[]デバッグ ヒストリー(Debug History)] &gt; [[]Hello, Android]</strong> を選択して、デバッグ モードに入ります。エミュレータでアプリケーションが再起動されますが、今度は、先ほど設定したブレークポイントに到達した時点で中断されます。その後 Eclipse のデバッグ パースペクティブ(Debug Perspective)で、他のアプリケーションで通常行うように、コードの内容を確認できます。</p>
+
+  <a href="images/hello_world_9.png"><img src="images/hello_world_9.png" style="height:230px" alt=""  /></a>
+
+
+<h2 id="noeclipse">Eclipse を使用せずにプロジェクトを作成する</h2>
+  
+  <p>Eclipse を使用していない場合(普段から使用している総合開発環境がある場合や、シンプルにテキスト エディタやコマンド ライン ツールを使用している場合など)は、Eclipse プラグインを利用することはできません。しかし心配は無用です。Eclipse を使用していないからといって何らかの機能が失われることはありません。</p>
+  
+  <p>Android Plugin for Eclipse は、単に Android SDK に含まれるツール セットをまとめたものに過ぎません(エミュレータ、aapt、adb、ddms などの個別のツールについては、<a href="{@docRoot}guide/developing/tools/index.html">こちらで別途説明</a>しています)。このため、これらのツールを別のツール、たとえば「Ant」のビルド ファイルなどでまとめることも可能です。</p>
+  
+  <p>Android SDK には、「android」という名前のツールが含まれています。このツールを使用すると、作成するプロジェクトのソース コードとディレクトリ スタブすべて、および Ant と互換性のある <code>build.xml</code> ファイルを作成することができます。これにより、プロジェクトをコマンド ラインで作成したり、普段使用している総合開発環境と統合したりすることができます。</p>
+  
+  <p>たとえば、Eclipse で作成されるものと同様の HelloAndroid プロジェクトを作成するには、次のコマンドを使用します。</p>
+  
+  <pre>
+android create project \
+    --package com.android.helloandroid \
+    --activity HelloAndroid \ 
+    --target 2 \
+    --path <em>&lt;path-to-your-project></em>/HelloAndroid 
+</pre>
+
+  <p>これにより、<em>path</em> で定義された場所に、プロジェクトに必要なフォルダとファイルが作成されます。</p>
+  
+  <p>SDK ツールを使用してプロジェクトを作成および構築する方法について詳しくは、「<a href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>」を参照してください。</p>
diff --git a/docs/html/intl/ja/index.jd b/docs/html/intl/ja/index.jd
new file mode 100644
index 0000000..a5378c9
--- /dev/null
+++ b/docs/html/intl/ja/index.jd
@@ -0,0 +1,159 @@
+home=true
+@jd:body
+
+
+	<div id="mainBodyFixed">
+              <div id="mainBodyLeft">			
+                    <div id="homeMiddle">
+                        <div id="topAnnouncement">
+                            <div id="homeTitle">
+                                <h2>デベロッパーへのお知らせ</h2>
+                            </div><!-- end homeTitle -->
+                            <div id="announcement-block">
+                            <!-- total max width is 520px -->
+                                <img src="/assets/images/home/android_adc.png" alt="Android Developer Challenge 2" width="232px" />
+                                <div id="announcement" style="width:275px">
+                                  <p>第2Android Developer Challengeが、遂に登場しました!このアプリケーション開発コンテストでは、Androidのユーザなら誰でも簡単に参加でき、一等の賞金は$250,000 です。登録の締切日は8月31日になります。</p>
+                                  <p><a href="http://code.google.com/android/adc/">Android  Developer Challengeについて詳しくはこちら &raquo;</a></p>
+                                </div> <!-- end annoucement -->
+                            </div> <!-- end annoucement-block -->  
+                        </div><!-- end topAnnouncement -->
+                        <div id="carouselMain" style="height:210px"> <!-- this height can be adjusted based on the content height -->
+                        </div>
+                            <div class="clearer"></div>
+                        <div id="carouselWheel">
+                            <div class="app-list-container" align="center"> 
+                                <a href="javascript:{}" id="arrow-left" onclick="" class="arrow-left-off"></a>
+                                <div id="list-clip">
+                                    <div style="left: 0px;" id="app-list">
+                                      <!-- populated by buildCarousel() -->
+                                    </div>
+                                </div><!-- end list-clip -->
+                                <a href="javascript:{ page_right(); }" id="arrow-right" onclick="" class="arrow-right-on"></a>
+                                <div class="clearer"></div>
+                            </div><!-- end app-list container -->
+                        </div><!-- end carouselWheel -->
+                    </div><!-- end homeMiddle -->
+
+                    <div style="clear:both">&nbsp;</div>
+              </div><!-- end mainBodyLeft -->
+
+              <div id="mainBodyRight">
+                      <table id="rightColumn">
+                              <tr>
+                                      <td class="imageCell"><a href="{@docRoot}sdk/index.html"><img src="{@docRoot}assets/images/icon_download.jpg" style="padding:0" /></a></td>
+                                      <td>
+                                              <h2 class="green">ダウンロード</h2>
+                                              <p>Android SDK には、優れたアプリケーションの作成に必要となるツール、サンプル コード、ドキュメントが含まれています。  </p>
+                                              <p><a href="{@docRoot}sdk/{@sdkCurrent}/index.html">詳細 &raquo;</a></p>
+                                      </td>
+                              </tr>
+                              <tr>
+                                      <td colspan="2"><div class="seperator">&nbsp;</div></td>
+                              </tr>
+                              <tr>
+                                      <td class="imageCell"><a href="http://www.android.com/market.html"><img src="{@docRoot}assets/images/icon_market.jpg" style="padding:0" /></a></td>
+                                      <td>
+                                              <h2 class="green">公開</h2>
+                                              <p>Android マーケットは、アプリケーションを携帯端末に配信するためのオープン サービスです。</p>
+                                              <p><a href="http://www.android.com/market.html">詳細 &raquo;</a></p>
+                                      </td>
+                              </tr>
+                              <tr>
+                                      <td colspan="2"><div class="seperator">&nbsp;</div></td>
+                              </tr>
+                              <tr>
+                                      <td class="imageCell"><a href="http://source.android.com"><img src="{@docRoot}assets/images/icon_contribute.jpg" style="padding:0" /></a></td>
+                                      <td>
+                                              <h2 class="green">貢献</h2>
+                                              <p>Android オープンソース プロジェクトでは、プラットフォーム全体のソースコードを公開しています。</p>
+                                              <p><a href="http://source.android.com">詳細 &raquo;</a></p>
+                                      </td>
+                              </tr>
+                              <tr>
+                                      <td colspan="2"><div class="seperator">&nbsp;</div></td>
+                              </tr>
+                              <tr>
+                                      <td class="imageCell"><a href="http://www.youtube.com/user/androiddevelopers"><img src="{@docRoot}assets/images/video-droid.png" style="padding:0" /></a></td>
+                                      <td>
+                                              <h2 class="green">再生</h2>
+                                              <object width="150" height="140"><param name="movie" value="http://www.youtube.com/v/GARMe7Km_gk&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/GARMe7Km_gk&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="150" height="140"></embed></object>
+                                              <p style="margin-top:1em"><a href="{@docRoot}videos/index.html">その他の Android 動画 &raquo;</a></p>
+                                      </td>
+                              </tr>
+
+                      </table>
+              </div>
+	</div>
+
+<!--[if lte IE 6]>
+  <style>
+    #arrow-left {
+      margin:0 0 0 5px;
+    }
+    #arrow-right {
+      margin-left:0;
+    }
+    .app-list-container {
+      margin: 37px 0 0 23px;
+    }
+    div#list-clip { 
+      width:468px;
+    }
+  </style>
+<![endif]-->
+
+<script type="text/javascript">
+
+// * -- carousel dictionary -- * //
+  /* layout:  imgLeft, imgRight, imgTop
+     icon:    image for carousel entry. cropped (height:70px, width:90px)
+     name:    string for carousel entry
+     img:     image for bulletin post. cropped (height: 170, width:230px)
+     title:   header for bulletin (optional, insert "" value to skip
+     desc:    the bulletin post. must include html tags. 
+  */
+
+  var droidList = {
+    'sdk': {
+      'layout':"imgLeft",
+      'icon':"sdk-small.png",
+      'name':"SDK 1.5 r3",
+      'img':"sdk-large.png",
+      'title':"Android 1.5 SDK",
+      'desc': "<p>Android 1.5 SDK の最新バージョンが公開されました。このリリースには Android 1.5 用の API、最新版デベロッパーツール、複数プラットフォーム(バージョン)サポート、そして Google API のアドオンが含まれています。</p><p><a href='{@docRoot}sdk/1.5_r3/index.html'>Android 1.5 SDK をダウンロード &raquo;</a></p>"
+    },
+    
+    'io': {
+      'layout':"imgLeft",
+      'icon':"io-small.png",
+      'name':"Google I/O",
+      'img':"io-large.png",
+      'title':"Google I/O Developer Conference",
+      'desc': "<p>Google I/O は、サンフランシスコの Moscone Center で 5 月 27~28 日に開催された開発者会議です。このイベントに参加できなかった方は、各アンドロイド向けセッションを、YouTube ビデオ資料で体験する事が可能<nobr>です</nobr>。</p><p><a href='{@docRoot}videos/index.html'>セッションを参照してください &raquo;</a></p>"
+    },
+
+    'mapskey': {
+      'layout':"imgLeft",
+      'icon':"maps-small.png",
+      'name':"Maps API キー",
+      'img':"maps-large.png",
+      'title':"Maps API キー",
+      'desc':"<p>MapView から Google マップを利用する Android アプリケーションを開発する場合は、アプリケーションを登録して Maps API キーを取得する必要があります。この API キーが無いアプリケーションは、Android 上で動作しません。キーの取得は、簡単な手順で行うことができます。</p><p><a href='http://code.google.com/android/add-ons/google-apis/maps-overview.html'>詳細 &raquo;</a></p>"
+    },
+
+    'devphone': {
+      'layout':"imgLeft",
+      'icon':"devphone-small.png",
+      'name':"Dev Phone 1",
+      'img':"devphone-large.png",
+      'title':"Android Dev Phone 1",
+      'desc': "<p>この携帯電話を使用することで、開発した Android アプリケーションの実行とデバッグを行うことができます。Android オペレーティングシステムを変更してからリビルドし、携帯電話に書き込むことができます。Android Dev Phone 1 は携帯通信会社に依存しておらず、<a href='http://market.android.com/publish'>Android マーケット</a>に登録済みのデベロッパーなら誰でも購入可能です。</p><p><a href='/guide/developing/device.html#dev-phone-1'>Android Dev Phone 1 の詳細&raquo;</a></p>"
+    }
+
+  }
+</script>
+<script type="text/javascript" src="{@docRoot}assets/carousel.js"></script>
+<script type="text/javascript">
+  initCarousel("sdk");
+</script>
diff --git a/docs/html/intl/ja/sdk/1.5_r2/installing.jd b/docs/html/intl/ja/sdk/1.5_r2/installing.jd
new file mode 100644
index 0000000..bcb1ffb
--- /dev/null
+++ b/docs/html/intl/ja/sdk/1.5_r2/installing.jd
@@ -0,0 +1,212 @@
+page.title=Android SDK のインストール
+@jd:body
+
+
+<p>このページでは、Android SDK をインストールして、開発環境を設定する方法について説明します。SDK をまだダウンロードしていない場合は、[<a href="{@docRoot}sdk/{@sdkCurrent}/index.html">ダウンロード</a>] ページからダウンロードしてください。SDK をダウンロードした後に、このページの手順を行ってください。</p>
+
+<p>インストール中に問題が発生した場合は、このページの下部にある<a href="#installnotes">インストールに関する注意事項</a>を参照してください。</p>
+
+<h4 style="margin-top">アップグレードする場合</h4>
+<p>SDK の以前のバージョンを使用してアプリケーションを既に開発している場合は、このページの代わりに、<a href="upgrading.html"><strong></strong>SDK のアップグレード</a></b> をご覧ください。
+</p>
+
+
+<h2 id="setup">インストールの準備</h2>
+
+<p>インストールを始める前に、開発用マシンが<a href="requirements.html">システム要件</a>を満たしていることを確認してください。
+</p>
+
+<p>Eclipse 環境に Android Development Tools(ADT)プラグインを組み込んだ開発環境は、Android 向け開発の初心者に最適です。プラグインを利用する場合は、コンピュータに Eclipse の適切なバージョン(3.3 以降)がインストールされていることを確認してください。Eclipse のインストールが必要な場合は、次の場所からダウンロードできます: </p>
+
+<p style="margin-left:2em;"><a href=
+"http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a></p>
+
+<p>Eclipse の Java バージョンまたは RCP バージョンをおすすめします。 </p>
+
+<h2 id="installingsdk">SDK のインストール</h2>
+
+<p>SDK のダウンロード後、お使いのマシンの適切な場所に .zip アーカイブを展開します。デフォルトでは、SDK ファイルは <code>android_sdk_<em>&lt;platform</em>&gt;_<em>&lt;release&gt;</em></code> ディレクトリに展開されます。このディレクトリには、ドキュメントのローカル コピー(ブラウザで <code>documentation.html</code> を開くと参照できます)と、<code>tools/</code>、<code>add-ons/</code>、<code>platforms/</code> などのサブディレクトリが含まれます。<code>platforms/</code> のサブディレクトリ内には、プラットフォームの各バージョンに固有のコードのサンプルが含まれる <code>samples/</code> があります。</p>
+
+<p>システム上に展開した SDK ディレクトリの名前とパスをメモしておきましょう。Android プラグインの設定時や、SDK ツールの使用時にこの SDK ディレクトリを参照する必要があります。</p>
+
+<p>SDK のプライマリディレクトリである <code>tools</code> のパスを、システム PATH に追加することをおすすめします。<code>tools/</code> プライマリディレクトリは、SDK フォルダのルートにあります。<code>tools</code> をパスに追加すると、Android Debug Bridge(adb)やその他のコマンド ライン <a href="{@docRoot}guide/developing/tools/index.html">ツール</a>を、ツールの格納されたディレクトの完全なパスを指定せずに実行できるようになります。 </p>
+<ul>
+    <li>Linux 上では <code>~/.bash_profile</code> ファイルまたは <code>~/.bashrc</code> ファイルを編集します。PATH 環境変数を設定している行を探し、その行に <code>tools/</code> ディレクトリへの完全なパスを追加します。PATH を設定する行が無い場合は、次の行を追加します:</li>
+
+    <ul><code>export PATH=${PATH}:<em>&lt;your_sdk_dir&gt;</em>/tools</code></ul>
+
+    <li>Mac 上では <code>.bash_profile</code> のホーム ディレクトリの内から同じファイルを検索し、Linux と同じように設定します。マシン上にまだ <code>.bash_profile</code> が無い場合は、ファイルを作成することができます。 </li>
+
+    <li>Windows 上では、[マイ コンピュータ] を右クリックし、[プロパティ] を選択します。[詳細設定] タブで [環境変数] ボタンをクリックし、表示されたダイアログで [システム環境変数] の [Path] をダブルクリックします。その Path に <code>tools/</code> ディレクトリへの完全なパスを追加します。 </li>
+  </ul>
+
+<p>今後 SDK をアップグレードする際は、PATH の設定を更新することを忘れないでください。別のディレクトリに SDK を展開する場合は、その新しい場所を PATH に設定する必要があります。</p>
+
+<p>Eclipse IDE を開発環境として使用する場合、Android Development Tools プラグインをインストールして Eclipse を設定する方法について、次のセクションの情報を参照してください。Eclipse を使用しない場合は、別の IDE を使用して Android アプリケーションを開発してから、SDK に含まれているツールを使用してコンパイル、デバッグ、配布を行うことができます(この場合は、<a href="#next">次のステップ</a>に進んでください)。</p>
+
+
+<h2 id="installingplugin">Eclipse 用 ADT プラグインのインストール</h2>
+
+<p>Android では、Android Development Tools(ADT)という Eclipse IDE 用のカスタム プラグインを提供しています。このプラグインは、Android アプリケーションの構築を可能にするために設計された、強力な統合環境です。プラグインによって Eclipse の機能が拡張され、新しい Android プロジェクトの設定、アプリケーションの UI の作成、Android Framework API に基づくコンポーネントの追加、Android SDK ツールを使用したアプリケーションのデバッグが可能になります。さらに、アプリケーションを配布するための署名済み(または未署名)の APK のエクスポートも簡単にできるようになります。</p>
+
+<p>一般的な Android 開発において、ADT を組み込んだ Eclipse の使用は強く推奨されており、Android 初心者に最も効率的な開発環境を提供します。(Eclipse 以外の IDE で作業する場合は、Eclipse や ADT をインストールする必要はありません。代わりに、SDK ツールを直接使用してアプリケーションを構築し、デバッグを行います)。</p>
+
+<p><a href="#setup">インストールの準備</a>で説明した手順に従って Eclipse をインストールした後は、次の手順に従って操作して ADT プラグインをダウンロードし、それぞれの Eclipse 環境にインストールします。 </p>
+
+<table style="font-size:100%">
+<tr><th>Eclipse 3.3(Europa)</th><th>Eclipse 3.4(Ganymede)</th></tr>
+<tr>
+<td width="45%">
+<!-- 3.3 steps -->
+<ol>
+    <li>Eclipse を起動し、[<strong>ヘルプ</strong>] &gt; [<strong>ソフトウェアの更新</strong>] &gt; [<strong>検索とインストール</strong>] を選択します。 </li>
+    <li>表示されるダイアログで [<strong>インストールする新規フィーチャーを検索</strong>] を選択して [<strong>次へ</strong>] をクリックします。 </li>
+    <li>[<strong>新規リモートサイト</strong>] をクリックします。 </li>
+    <li>表示されるダイアログ ボックスで、リモート サイトの名前(例: 「Android Plugin」)を入力し、URL を入力します:
+        <pre>https://dl-ssl.google.com/android/eclipse/</pre>
+        <p>プラグインが入手できない場合は、URL の「https」の代わりに「http」を使用してみてください(セキュリティ上の理由からは、https をおすすめします)。</p>
+        <p>[<strong>OK</strong>] をクリックします。</p> </li>
+    <li>検索リストに新しいサイトが追加されており、チェックボックスがオンの状態で表示されるはずです。[<strong>終了</strong>] をクリックします。 </li>
+    <li>次の [検索結果] ダイアログボックスで、「Android Plugin」のチェックボックスをオンにします。これにより、そこに含まれているツール「Android DDMS」と「Android Development Tools」も自動的にオンになります。[<strong>次へ</strong>] をクリックします。</li>
+    <li>使用許諾契約を読み、同意して、[<strong>次へ</strong>] をクリックします。 </li>
+    <li>次のインストール ウィンドウで [<strong>終了</strong>] をクリックします。 </li>
+    <li>ADT プラグインはデジタル署名されていません。[<strong>すべてインストール</strong>] をクリックしてインストールを許可します。 </li>
+    <li>Eclipse を再起動します。 </li>
+</ol>
+
+</td>
+<td>
+
+<!-- 3.4 steps -->
+<ol>
+    <li>Eclipse を起動し、[<strong>ヘルプ</strong>] &gt; [<strong>ソフトウェアの更新</strong>] を選択します。</li>
+    <li>表示されるダイアログで [<strong>使用可能なソフトウェア</strong>] タブをクリックします。 </li>
+    <li>[<strong>サイトの追加</strong>] をクリックします。 </li>
+    <li>次の場所を入力します:
+      <pre>https://dl-ssl.google.com/android/eclipse/</pre>
+        <p>プラグインが入手できない場合は、場所の URL の「https」の代わりに「http」を使用してみてください(セキュリティ上の理由からは、https をおすすめします)。</p>   
+      <p>[<strong>OK</strong>] をクリックします。</p></li>
+    <li>[使用可能なソフトウェア] のタブに戻ると、上記の URL によるプラグインとその中に含まれる「Developer Tools」が表示されているはずです。「Developer Tools」の横のチェックボックスをオンにし、[<strong>インストール</strong>] をクリックします。</li>
+    <li>次のインストール ウィンドウで、「Android DDMS」と「Android Development Tools」の両方のチェックボックスがオンになっていることを確認します。[<strong>次へ</strong>] をクリックします。 </li>
+    <li>使用許諾契約を読み、同意して、[<strong>終了</strong>] をクリックします。</li>
+    <li>Eclipse を再起動します。 </li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+<p>次に、Eclipse の設定を変更して、Android SDK ディレクトリを指すように変更します:</p>
+<ol>
+    <li>[<strong>ウィンドウ</strong>] &gt; [<strong>設定</strong>] を選択して、[設定] パネルを開きます(Mac 上では [<strong>Eclipse</strong>] &gt; [<strong>設定</strong>])。</li>
+    <li>左側のパネルで [<strong>Android</strong>] を選択します。 </li>
+    <li>メイン パネルの [<em>SDK Location</em>] で [<strong>参照</strong>] をクリックし、ダウンロードした SDK ディレクトリを探します。 </li>
+    <li>[<strong>適用</strong>] をクリックして、[<strong>OK</strong>] をクリックします。</li>
+</ol>
+
+<p>これで完了です。問題なく完了した場合は、Android アプリケーション開発を始める準備が整っています。開発を始めるヒントについては、<a href="#next">次のステップ</a>のセクションをご覧ください。 </p>
+
+
+<h3 id="troubleshooting">ADT のインストールでのトラブルシューティング</h3>
+<p> 
+上記の手順で、ADT プラグインのダウンロードに問題が生じた場合のヒントは次のとおりです: </p>
+
+<ul>
+  <li>Eclipse から ADT プラグインを含むリモート更新サイトが見つからない場合は、リモート サイトとして指定した URL の https を http に変更してみます。つまり、次のリモート サイトの URL を設定します:
+  <pre>http://dl-ssl.google.com/android/eclipse/</pre></li>
+  <li>ファイアウォール(社内のファイアウォールなど)の内部にいる場合、Eclipse でプロキシ情報が正しく設定されていることを確認してください。Eclipse 3.3/3.4 でプロキシ情報を設定するには、Eclipse のメイン メニューから [<strong>ウィンドウ</strong>](Mac 上では [<strong>Eclipse</strong>])&gt; [<strong>環境設定</strong>] &gt; [<strong>一般</strong>] &gt; [<strong>ネットワーク接続</strong>] を選択します。</li>
+</ul>
+<p> 
+それでも Eclipse を使用して ADT プラグインをリモート更新サイトとしてダウンロードできない場合は、ADT zip ファイルをローカル マシン上にダウンロードして、手動でインストールすることができます:
+</p>
+<ol>
+  <li><a href="{@docRoot}sdk/adt_download.html">ADT zip ファイルをダウンロードします</a>(展開はしないでください)。</li>
+  <li>デフォルトのインストール手順(上記)のステップ 1 と 2 のとおりに操作します。</li>
+  <li>Eclipse 3.3 では [<strong>新規アーカイブ・サイト</strong>] をクリックします。<br/>Eclipse 3.4 では [<strong>サイトの追加</strong>] をクリックして、[<strong>アーカイブ</strong>] をクリックします。</li>
+  <li>ダウンロードした zip ファイルを参照して選択してください。</li>
+  <li>上記のステップ 5 から残りの手順に従って操作します。</li>
+</ol>
+<p>zip ファイルからインストールしたプラグインを後でアップデートする場合は、デフォルトのアップデート手順の代わりに、もう一度この手順どおりに操作する必要があります。</p>
+
+<h4>その他のインストール エラー</h4>
+
+<p>オプションの Eclipse コンポーネント(WST など)を必要とする ADT の機能があります。ADT のインストール時にエラーが発生した場合、お使いの Eclipse インストール環境にこうしたコンポーネントが含まれていない可能性があります。必要なコンポーネントを Eclipse インストール環境に簡単に追加する方法について詳しくは、トラブルシューティング トピック <a href="{@docRoot}guide/appendix/faq/troubleshooting.html#installeclipsecomponents">ADT インストールエラー: "requires plug-in org.eclipse.wst.sse.ui"</a> をご覧ください。</p>
+
+<h4>Linux ユーザーの場合</h4>
+<p>Eclipse 用 ADT プラグインのインストール時に、次のエラーが発生する場合があります。 
+<pre>
+An error occurred during provisioning.
+Cannot connect to keystore.
+JKS</pre>
+<p>
+この場合、お使いの開発用マシンに適切な Java VM が搭載されていません。Sun Java 6 をインストールするとこの問題が解決し、ADT プラグインを再インストールすることができます。</p>
+
+
+<h2 id="next">次のステップ</h2>
+<p>インストールを完了すると、アプリケーションの開発を始める準備が整います。開発を始める方法をいくつか紹介します: </p>
+
+<p><strong>Android の詳細の学習</strong></p>
+<ul>
+  <li><a href="{@docRoot}guide/index.html">デベロッパー ガイド</a>と、ガイドに説明されている情報の種類を参照します。</li>
+  <li>Android をプラットフォームとして紹介している <a
+  href="{@docRoot}guide/basics/what-is-android.html">Android とは</a>を読みます。</li>
+  <li><a href="{@docRoot}guide/topics/fundamentals.html">アプリケーションの基礎</a>を参照して、Android フレームワークとそこでのアプリケーションの実行方法について学びます。</li>
+  <li>[<a
+  href="{@docRoot}reference/packages.html">リファレンス</a>] タブの Android Framework API の仕様を参照します。</li>
+</ul>
+
+<p><strong>SDK の探索</strong></p>
+<ul>
+  <li>利用可能な<a
+  href="{@docRoot}guide/developing/tools/index.html">開発ツール</a>の概要を把握します。</li>
+  <li><a
+  href="{@docRoot}guide/developing/eclipse-adt.html">Eclipse/ADT</a> または<a href="{@docRoot}guide/developing/other-ide.html">別の IDE</a> での開発方法を参照します。
+  </li>
+</ul>
+
+<p><strong>サンプル コードの参照</strong></p>
+<ul>
+  <li><a href="{@docRoot}guide/tutorials/hello-world.html">Hello World アプリケーション</a>を構築します(特に Eclipse ユーザーにおすすめです)。</li>
+  <li><a href="{@docRoot}guide/tutorials/notepad/index.html">Notepad チュートリアル</a>に沿って Android アプリケーションを完全に構築します。 </li>
+  <li><code><em>&lt;sdk&gt;</em>/platforms/<em>&lt;platfrom&gt;</em>/samples</code> に収められている他のサンプル アプリケーションのいずれかを新しいプロジェクトとして作成し、自分の開発環境でコンパイルし、実行します。</li>
+</ul>
+
+<p><strong>Android デベロッパー グループへのアクセス</strong></p>
+<ul>
+  <li>[<a
+  href="{@docRoot}community/index.html">コミュニティ</a>] タブで、Android デベロッパー グループの一覧を参照します。特に <a href="http://groups.google.com/group/android-developers">Android Developers</a> グループは、Android デベロッパー コミュニティがどういうものかを知るのに参考になります。</li>
+</ul>
+
+
+<h2 id="installnotes">インストールに関する注意事項</h2>
+
+<h3>Ubuntu Linux に関する注意事項</h3>
+
+<ul>
+  <li>開発マシン上で Java をインストールして設定する方法については、次のリソースが参考になります: 
+    <ul>
+      <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/Java </a></li>
+      <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/JavaInstallation</a></li>
+    </ul>
+  </li>
+  <li>Android SDK と ADT プラグインをインストールする前に、Java と Eclipse をインストールする手順は次のとおりです。
+    <ol>
+      <li>開発マシン上で 64 ビット版を実行している場合は、<code>apt-get:</code> を使用して <code>ia32-libs</code> パッケージをインストールする必要があります:
+      <pre>apt-get install ia32-libs</pre>
+      </li>
+      <li>次に Java をインストールします: <pre>apt-get install sun-java6-bin</pre></li>
+      <li>Ubuntu パッケージ マネージャでは現在、Eclipse 3.3 バージョンのダウンロードを提供していないので、eclipse.org( <a
+      href="http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a> )から Eclipse をダウンロードすることをおすすめします。Eclipse の Java バージョンまたは RCP バージョンをおすすめします。</li>
+      <li>上記のセクションの手順どおりに SDK と ADT プラグインをインストールします。 </li>
+    </ol>
+  </li>
+</ul>
+
+<h3>その他の Linux に関する注意事項</h3>
+
+<ul>
+  <li>開発用コンピュータに JDK が既にインストールされている場合は、<a href="requirements.html">システム要件</a>に記載されているバージョン要件を満たしていることを確認してください。特に、ディストリビューションによっては JDK 1.4 または Gnu Compiler for Java が組み込まれている場合があります。これらは Android の開発ではサポートされていないので、ご注意ください。</li>
+</ul>
+
+
+
diff --git a/docs/html/intl/ja/sdk/1.5_r3/installing.jd b/docs/html/intl/ja/sdk/1.5_r3/installing.jd
new file mode 100644
index 0000000..bcb1ffb
--- /dev/null
+++ b/docs/html/intl/ja/sdk/1.5_r3/installing.jd
@@ -0,0 +1,212 @@
+page.title=Android SDK のインストール
+@jd:body
+
+
+<p>このページでは、Android SDK をインストールして、開発環境を設定する方法について説明します。SDK をまだダウンロードしていない場合は、[<a href="{@docRoot}sdk/{@sdkCurrent}/index.html">ダウンロード</a>] ページからダウンロードしてください。SDK をダウンロードした後に、このページの手順を行ってください。</p>
+
+<p>インストール中に問題が発生した場合は、このページの下部にある<a href="#installnotes">インストールに関する注意事項</a>を参照してください。</p>
+
+<h4 style="margin-top">アップグレードする場合</h4>
+<p>SDK の以前のバージョンを使用してアプリケーションを既に開発している場合は、このページの代わりに、<a href="upgrading.html"><strong></strong>SDK のアップグレード</a></b> をご覧ください。
+</p>
+
+
+<h2 id="setup">インストールの準備</h2>
+
+<p>インストールを始める前に、開発用マシンが<a href="requirements.html">システム要件</a>を満たしていることを確認してください。
+</p>
+
+<p>Eclipse 環境に Android Development Tools(ADT)プラグインを組み込んだ開発環境は、Android 向け開発の初心者に最適です。プラグインを利用する場合は、コンピュータに Eclipse の適切なバージョン(3.3 以降)がインストールされていることを確認してください。Eclipse のインストールが必要な場合は、次の場所からダウンロードできます: </p>
+
+<p style="margin-left:2em;"><a href=
+"http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a></p>
+
+<p>Eclipse の Java バージョンまたは RCP バージョンをおすすめします。 </p>
+
+<h2 id="installingsdk">SDK のインストール</h2>
+
+<p>SDK のダウンロード後、お使いのマシンの適切な場所に .zip アーカイブを展開します。デフォルトでは、SDK ファイルは <code>android_sdk_<em>&lt;platform</em>&gt;_<em>&lt;release&gt;</em></code> ディレクトリに展開されます。このディレクトリには、ドキュメントのローカル コピー(ブラウザで <code>documentation.html</code> を開くと参照できます)と、<code>tools/</code>、<code>add-ons/</code>、<code>platforms/</code> などのサブディレクトリが含まれます。<code>platforms/</code> のサブディレクトリ内には、プラットフォームの各バージョンに固有のコードのサンプルが含まれる <code>samples/</code> があります。</p>
+
+<p>システム上に展開した SDK ディレクトリの名前とパスをメモしておきましょう。Android プラグインの設定時や、SDK ツールの使用時にこの SDK ディレクトリを参照する必要があります。</p>
+
+<p>SDK のプライマリディレクトリである <code>tools</code> のパスを、システム PATH に追加することをおすすめします。<code>tools/</code> プライマリディレクトリは、SDK フォルダのルートにあります。<code>tools</code> をパスに追加すると、Android Debug Bridge(adb)やその他のコマンド ライン <a href="{@docRoot}guide/developing/tools/index.html">ツール</a>を、ツールの格納されたディレクトの完全なパスを指定せずに実行できるようになります。 </p>
+<ul>
+    <li>Linux 上では <code>~/.bash_profile</code> ファイルまたは <code>~/.bashrc</code> ファイルを編集します。PATH 環境変数を設定している行を探し、その行に <code>tools/</code> ディレクトリへの完全なパスを追加します。PATH を設定する行が無い場合は、次の行を追加します:</li>
+
+    <ul><code>export PATH=${PATH}:<em>&lt;your_sdk_dir&gt;</em>/tools</code></ul>
+
+    <li>Mac 上では <code>.bash_profile</code> のホーム ディレクトリの内から同じファイルを検索し、Linux と同じように設定します。マシン上にまだ <code>.bash_profile</code> が無い場合は、ファイルを作成することができます。 </li>
+
+    <li>Windows 上では、[マイ コンピュータ] を右クリックし、[プロパティ] を選択します。[詳細設定] タブで [環境変数] ボタンをクリックし、表示されたダイアログで [システム環境変数] の [Path] をダブルクリックします。その Path に <code>tools/</code> ディレクトリへの完全なパスを追加します。 </li>
+  </ul>
+
+<p>今後 SDK をアップグレードする際は、PATH の設定を更新することを忘れないでください。別のディレクトリに SDK を展開する場合は、その新しい場所を PATH に設定する必要があります。</p>
+
+<p>Eclipse IDE を開発環境として使用する場合、Android Development Tools プラグインをインストールして Eclipse を設定する方法について、次のセクションの情報を参照してください。Eclipse を使用しない場合は、別の IDE を使用して Android アプリケーションを開発してから、SDK に含まれているツールを使用してコンパイル、デバッグ、配布を行うことができます(この場合は、<a href="#next">次のステップ</a>に進んでください)。</p>
+
+
+<h2 id="installingplugin">Eclipse 用 ADT プラグインのインストール</h2>
+
+<p>Android では、Android Development Tools(ADT)という Eclipse IDE 用のカスタム プラグインを提供しています。このプラグインは、Android アプリケーションの構築を可能にするために設計された、強力な統合環境です。プラグインによって Eclipse の機能が拡張され、新しい Android プロジェクトの設定、アプリケーションの UI の作成、Android Framework API に基づくコンポーネントの追加、Android SDK ツールを使用したアプリケーションのデバッグが可能になります。さらに、アプリケーションを配布するための署名済み(または未署名)の APK のエクスポートも簡単にできるようになります。</p>
+
+<p>一般的な Android 開発において、ADT を組み込んだ Eclipse の使用は強く推奨されており、Android 初心者に最も効率的な開発環境を提供します。(Eclipse 以外の IDE で作業する場合は、Eclipse や ADT をインストールする必要はありません。代わりに、SDK ツールを直接使用してアプリケーションを構築し、デバッグを行います)。</p>
+
+<p><a href="#setup">インストールの準備</a>で説明した手順に従って Eclipse をインストールした後は、次の手順に従って操作して ADT プラグインをダウンロードし、それぞれの Eclipse 環境にインストールします。 </p>
+
+<table style="font-size:100%">
+<tr><th>Eclipse 3.3(Europa)</th><th>Eclipse 3.4(Ganymede)</th></tr>
+<tr>
+<td width="45%">
+<!-- 3.3 steps -->
+<ol>
+    <li>Eclipse を起動し、[<strong>ヘルプ</strong>] &gt; [<strong>ソフトウェアの更新</strong>] &gt; [<strong>検索とインストール</strong>] を選択します。 </li>
+    <li>表示されるダイアログで [<strong>インストールする新規フィーチャーを検索</strong>] を選択して [<strong>次へ</strong>] をクリックします。 </li>
+    <li>[<strong>新規リモートサイト</strong>] をクリックします。 </li>
+    <li>表示されるダイアログ ボックスで、リモート サイトの名前(例: 「Android Plugin」)を入力し、URL を入力します:
+        <pre>https://dl-ssl.google.com/android/eclipse/</pre>
+        <p>プラグインが入手できない場合は、URL の「https」の代わりに「http」を使用してみてください(セキュリティ上の理由からは、https をおすすめします)。</p>
+        <p>[<strong>OK</strong>] をクリックします。</p> </li>
+    <li>検索リストに新しいサイトが追加されており、チェックボックスがオンの状態で表示されるはずです。[<strong>終了</strong>] をクリックします。 </li>
+    <li>次の [検索結果] ダイアログボックスで、「Android Plugin」のチェックボックスをオンにします。これにより、そこに含まれているツール「Android DDMS」と「Android Development Tools」も自動的にオンになります。[<strong>次へ</strong>] をクリックします。</li>
+    <li>使用許諾契約を読み、同意して、[<strong>次へ</strong>] をクリックします。 </li>
+    <li>次のインストール ウィンドウで [<strong>終了</strong>] をクリックします。 </li>
+    <li>ADT プラグインはデジタル署名されていません。[<strong>すべてインストール</strong>] をクリックしてインストールを許可します。 </li>
+    <li>Eclipse を再起動します。 </li>
+</ol>
+
+</td>
+<td>
+
+<!-- 3.4 steps -->
+<ol>
+    <li>Eclipse を起動し、[<strong>ヘルプ</strong>] &gt; [<strong>ソフトウェアの更新</strong>] を選択します。</li>
+    <li>表示されるダイアログで [<strong>使用可能なソフトウェア</strong>] タブをクリックします。 </li>
+    <li>[<strong>サイトの追加</strong>] をクリックします。 </li>
+    <li>次の場所を入力します:
+      <pre>https://dl-ssl.google.com/android/eclipse/</pre>
+        <p>プラグインが入手できない場合は、場所の URL の「https」の代わりに「http」を使用してみてください(セキュリティ上の理由からは、https をおすすめします)。</p>   
+      <p>[<strong>OK</strong>] をクリックします。</p></li>
+    <li>[使用可能なソフトウェア] のタブに戻ると、上記の URL によるプラグインとその中に含まれる「Developer Tools」が表示されているはずです。「Developer Tools」の横のチェックボックスをオンにし、[<strong>インストール</strong>] をクリックします。</li>
+    <li>次のインストール ウィンドウで、「Android DDMS」と「Android Development Tools」の両方のチェックボックスがオンになっていることを確認します。[<strong>次へ</strong>] をクリックします。 </li>
+    <li>使用許諾契約を読み、同意して、[<strong>終了</strong>] をクリックします。</li>
+    <li>Eclipse を再起動します。 </li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+<p>次に、Eclipse の設定を変更して、Android SDK ディレクトリを指すように変更します:</p>
+<ol>
+    <li>[<strong>ウィンドウ</strong>] &gt; [<strong>設定</strong>] を選択して、[設定] パネルを開きます(Mac 上では [<strong>Eclipse</strong>] &gt; [<strong>設定</strong>])。</li>
+    <li>左側のパネルで [<strong>Android</strong>] を選択します。 </li>
+    <li>メイン パネルの [<em>SDK Location</em>] で [<strong>参照</strong>] をクリックし、ダウンロードした SDK ディレクトリを探します。 </li>
+    <li>[<strong>適用</strong>] をクリックして、[<strong>OK</strong>] をクリックします。</li>
+</ol>
+
+<p>これで完了です。問題なく完了した場合は、Android アプリケーション開発を始める準備が整っています。開発を始めるヒントについては、<a href="#next">次のステップ</a>のセクションをご覧ください。 </p>
+
+
+<h3 id="troubleshooting">ADT のインストールでのトラブルシューティング</h3>
+<p> 
+上記の手順で、ADT プラグインのダウンロードに問題が生じた場合のヒントは次のとおりです: </p>
+
+<ul>
+  <li>Eclipse から ADT プラグインを含むリモート更新サイトが見つからない場合は、リモート サイトとして指定した URL の https を http に変更してみます。つまり、次のリモート サイトの URL を設定します:
+  <pre>http://dl-ssl.google.com/android/eclipse/</pre></li>
+  <li>ファイアウォール(社内のファイアウォールなど)の内部にいる場合、Eclipse でプロキシ情報が正しく設定されていることを確認してください。Eclipse 3.3/3.4 でプロキシ情報を設定するには、Eclipse のメイン メニューから [<strong>ウィンドウ</strong>](Mac 上では [<strong>Eclipse</strong>])&gt; [<strong>環境設定</strong>] &gt; [<strong>一般</strong>] &gt; [<strong>ネットワーク接続</strong>] を選択します。</li>
+</ul>
+<p> 
+それでも Eclipse を使用して ADT プラグインをリモート更新サイトとしてダウンロードできない場合は、ADT zip ファイルをローカル マシン上にダウンロードして、手動でインストールすることができます:
+</p>
+<ol>
+  <li><a href="{@docRoot}sdk/adt_download.html">ADT zip ファイルをダウンロードします</a>(展開はしないでください)。</li>
+  <li>デフォルトのインストール手順(上記)のステップ 1 と 2 のとおりに操作します。</li>
+  <li>Eclipse 3.3 では [<strong>新規アーカイブ・サイト</strong>] をクリックします。<br/>Eclipse 3.4 では [<strong>サイトの追加</strong>] をクリックして、[<strong>アーカイブ</strong>] をクリックします。</li>
+  <li>ダウンロードした zip ファイルを参照して選択してください。</li>
+  <li>上記のステップ 5 から残りの手順に従って操作します。</li>
+</ol>
+<p>zip ファイルからインストールしたプラグインを後でアップデートする場合は、デフォルトのアップデート手順の代わりに、もう一度この手順どおりに操作する必要があります。</p>
+
+<h4>その他のインストール エラー</h4>
+
+<p>オプションの Eclipse コンポーネント(WST など)を必要とする ADT の機能があります。ADT のインストール時にエラーが発生した場合、お使いの Eclipse インストール環境にこうしたコンポーネントが含まれていない可能性があります。必要なコンポーネントを Eclipse インストール環境に簡単に追加する方法について詳しくは、トラブルシューティング トピック <a href="{@docRoot}guide/appendix/faq/troubleshooting.html#installeclipsecomponents">ADT インストールエラー: "requires plug-in org.eclipse.wst.sse.ui"</a> をご覧ください。</p>
+
+<h4>Linux ユーザーの場合</h4>
+<p>Eclipse 用 ADT プラグインのインストール時に、次のエラーが発生する場合があります。 
+<pre>
+An error occurred during provisioning.
+Cannot connect to keystore.
+JKS</pre>
+<p>
+この場合、お使いの開発用マシンに適切な Java VM が搭載されていません。Sun Java 6 をインストールするとこの問題が解決し、ADT プラグインを再インストールすることができます。</p>
+
+
+<h2 id="next">次のステップ</h2>
+<p>インストールを完了すると、アプリケーションの開発を始める準備が整います。開発を始める方法をいくつか紹介します: </p>
+
+<p><strong>Android の詳細の学習</strong></p>
+<ul>
+  <li><a href="{@docRoot}guide/index.html">デベロッパー ガイド</a>と、ガイドに説明されている情報の種類を参照します。</li>
+  <li>Android をプラットフォームとして紹介している <a
+  href="{@docRoot}guide/basics/what-is-android.html">Android とは</a>を読みます。</li>
+  <li><a href="{@docRoot}guide/topics/fundamentals.html">アプリケーションの基礎</a>を参照して、Android フレームワークとそこでのアプリケーションの実行方法について学びます。</li>
+  <li>[<a
+  href="{@docRoot}reference/packages.html">リファレンス</a>] タブの Android Framework API の仕様を参照します。</li>
+</ul>
+
+<p><strong>SDK の探索</strong></p>
+<ul>
+  <li>利用可能な<a
+  href="{@docRoot}guide/developing/tools/index.html">開発ツール</a>の概要を把握します。</li>
+  <li><a
+  href="{@docRoot}guide/developing/eclipse-adt.html">Eclipse/ADT</a> または<a href="{@docRoot}guide/developing/other-ide.html">別の IDE</a> での開発方法を参照します。
+  </li>
+</ul>
+
+<p><strong>サンプル コードの参照</strong></p>
+<ul>
+  <li><a href="{@docRoot}guide/tutorials/hello-world.html">Hello World アプリケーション</a>を構築します(特に Eclipse ユーザーにおすすめです)。</li>
+  <li><a href="{@docRoot}guide/tutorials/notepad/index.html">Notepad チュートリアル</a>に沿って Android アプリケーションを完全に構築します。 </li>
+  <li><code><em>&lt;sdk&gt;</em>/platforms/<em>&lt;platfrom&gt;</em>/samples</code> に収められている他のサンプル アプリケーションのいずれかを新しいプロジェクトとして作成し、自分の開発環境でコンパイルし、実行します。</li>
+</ul>
+
+<p><strong>Android デベロッパー グループへのアクセス</strong></p>
+<ul>
+  <li>[<a
+  href="{@docRoot}community/index.html">コミュニティ</a>] タブで、Android デベロッパー グループの一覧を参照します。特に <a href="http://groups.google.com/group/android-developers">Android Developers</a> グループは、Android デベロッパー コミュニティがどういうものかを知るのに参考になります。</li>
+</ul>
+
+
+<h2 id="installnotes">インストールに関する注意事項</h2>
+
+<h3>Ubuntu Linux に関する注意事項</h3>
+
+<ul>
+  <li>開発マシン上で Java をインストールして設定する方法については、次のリソースが参考になります: 
+    <ul>
+      <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/Java </a></li>
+      <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/JavaInstallation</a></li>
+    </ul>
+  </li>
+  <li>Android SDK と ADT プラグインをインストールする前に、Java と Eclipse をインストールする手順は次のとおりです。
+    <ol>
+      <li>開発マシン上で 64 ビット版を実行している場合は、<code>apt-get:</code> を使用して <code>ia32-libs</code> パッケージをインストールする必要があります:
+      <pre>apt-get install ia32-libs</pre>
+      </li>
+      <li>次に Java をインストールします: <pre>apt-get install sun-java6-bin</pre></li>
+      <li>Ubuntu パッケージ マネージャでは現在、Eclipse 3.3 バージョンのダウンロードを提供していないので、eclipse.org( <a
+      href="http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a> )から Eclipse をダウンロードすることをおすすめします。Eclipse の Java バージョンまたは RCP バージョンをおすすめします。</li>
+      <li>上記のセクションの手順どおりに SDK と ADT プラグインをインストールします。 </li>
+    </ol>
+  </li>
+</ul>
+
+<h3>その他の Linux に関する注意事項</h3>
+
+<ul>
+  <li>開発用コンピュータに JDK が既にインストールされている場合は、<a href="requirements.html">システム要件</a>に記載されているバージョン要件を満たしていることを確認してください。特に、ディストリビューションによっては JDK 1.4 または Gnu Compiler for Java が組み込まれている場合があります。これらは Android の開発ではサポートされていないので、ご注意ください。</li>
+</ul>
+
+
+
diff --git a/docs/html/sdk/1.5_r2/installing.jd b/docs/html/sdk/1.5_r2/installing.jd
index 69b2c1b..1530dc5 100644
--- a/docs/html/sdk/1.5_r2/installing.jd
+++ b/docs/html/sdk/1.5_r2/installing.jd
@@ -9,7 +9,7 @@
 <p>This page describes how to install the Android SDK and set up your
 development environment. If you haven't downloaded the SDK, you can
 do so from the 
-<a href="{@docRoot}sdk/1.5_r2/index.html">Download</a> page. Once you've downloaded
+<a href="index.html">Download</a> page. Once you've downloaded
 the SDK, return here.</p>
 
 <p>If you encounter any problems during installation, see the 
@@ -19,7 +19,7 @@
 <h4 style="margin-top">Upgrading?</h4>
 <p>If you have already developed applications using an earlier version
 of the SDK, please read 
-<a href="{@docRoot}sdk/1.5_r2/upgrading.html"><strong>Upgrading the
+<a href="upgrading.html"><strong>Upgrading the
 SDK</strong></a></b>, instead.
 </p>
 
@@ -27,7 +27,7 @@
 <h2 id="setup">Preparing for Installation</h2>
 
 <p>Before you begin, take a moment to confirm that your development machine meets the 
-<a href="{@docRoot}sdk/1.5_r2/requirements.html">System Requirements</a>.
+<a href="requirements.html">System Requirements</a>.
 </p>
 
 <p>If you will be developing on Eclipse with the Android Development
@@ -323,7 +323,7 @@
 <ul>
   <li>If JDK is already installed on your development computer, please
   take a moment to make sure that it meets the version requirements listed
-  in the <a href="{@docRoot}sdk/1.1_r1/requirements.html">System Requirements</a>.
+  in the <a href="{@docRoot}sdk/{@sdkCurrent}/requirements.html">System Requirements</a>.
   In particular, note that some Linux distributions may include JDK 1.4 or Gnu
   Compiler for Java, both of which are not supported for Android development.</li>
 </ul>
diff --git a/docs/html/sdk/1.5_r3/index.jd b/docs/html/sdk/1.5_r3/index.jd
new file mode 100644
index 0000000..3364f93
--- /dev/null
+++ b/docs/html/sdk/1.5_r3/index.jd
@@ -0,0 +1,87 @@
+sdk.version=1.5
+sdk.rel.id=3
+sdk.date=July 2009
+
+sdk.win_download=android-sdk-windows-1.5_r3.zip
+sdk.win_bytes=191477853
+sdk.win_checksum=1725fd6963ce69102ba7192568dfc711
+
+sdk.mac_download=android-sdk-mac_x86-1.5_r3.zip
+sdk.mac_bytes=183024673
+sdk.mac_checksum=b1bafdaefdcec89a14b604b504e7daec
+
+sdk.linux_download=android-sdk-linux_x86-1.5_r3.zip
+sdk.linux_bytes=178117561
+sdk.linux_checksum=350d0211678ced38da926b8c9ffa4fac
+
+page.title=Android 1.5 SDK, Release 3
+@jd:body
+
+<p>For more information on this SDK release, read the
+<a href="{@docRoot}sdk/RELEASENOTES.html#1.5_r3">Release Notes</a>.</p>
+
+<h2>SDK Contents</h2>
+
+<h4>Development tools</h4>
+
+<p>The SDK includes a full set of tools for developing and debugging application code and designing an application UI. You can read about the tools in the  
+<a href="{@docRoot}guide/developing/tools/index.html">Dev Guide</a> and access them in the <code>&lt;sdk&gt;/tools/</code> directory. 
+
+<p>The tools package in this SDK includes updates from those provided in the previous SDK. The tools also require a different project structure. To use the new tools, you need to migrate your applications to the new development environment. For more information about how to migrate, see <a href="upgrading.html">Upgrading the SDK</a>.
+
+<p>For more information about the new tools features, see the <a href="{@docRoot}sdk/RELEASENOTES.html">SDK Release Notes</a>. 
+
+<h4 id="system_images">Android Platforms</h4>
+
+<p>This SDK includes multiple Android platform versions that you use to develop applications. For each version, both a fully compliant Android library and system image are provided. The table below lists the platform versions included in this SDK. For more information about a platform version &mdash; features, applications included, localizations, API changes, and so on &mdash; see its Version Notes. </p>
+
+<table style="margin-right:1em;" width="80%">
+<tr>
+<th><nobr>Platform</nobr></th><th><nobr>API Level</nobr></th><th>Notes</th><th>Description</th>
+</tr>
+
+<tr>
+<td width="5%"><nobr>Android 1.5</nobr></td>
+<td  width="5%">3</td>
+<td  width="5%"><nobr><a href="{@docRoot}sdk/android-1.5.html">Version Notes</a></nobr></td>
+<td>Includes a standard Android 1.5 library and system image with a set of development applications. Does not include any external libraries (such as the Maps external library).</td>
+</tr>
+<tr>
+<td width="5%"><nobr>Android 1.1</nobr></td>
+<td  width="5%">2</td>
+<td  width="5%"><nobr><a href="{@docRoot}sdk/android-1.1.html">Version Notes</a></nobr></td>
+<td>Includes a compliant Android 1.1 library and system image with a set of development applications. Also includes the Maps external library (due to legacy build system issues).</td>
+</tr>
+</table>
+
+<h4 id="system_images">SDK Add-Ons</h4>
+
+<p>An SDK add-on provides a development environment for an Android external library or a customized (but fully compliant) Android system image. This SDK includes the SDK add-on listed below. The Android system API Level required by the add-on is noted.</p>
+
+<table style="margin-right:1em;" width="80%">
+<tr>
+<th><nobr>Add-On</nobr></th><th><nobr>API Level</nobr></th><th>Notes</th><th>Description</th>
+</tr>
+<tr>
+<td width="5%"><nobr>Google APIs</nobr></td>
+<td  width="5%">3</td>
+<td  width="5%">&nbsp;</td>
+<td>Includes the com.google.android.maps external library, a compliant 
+system image, a {@link android.location.Geocoder Geocoder}
+backend service implementation, documentation, and sample code. </td>
+</tr>
+</table>
+
+<h4>Sample Code and Applications</h4>
+
+<p>You can look at a variety of tutorials and samples in the <a href="{@docRoot}guide/samples/index.html">Dev Guide</a> and access the sample code itself
+in the <code>&lt;sdk&gt;/platforms/android-1.5/samples/</code> directory of the SDK package. Note the new location &mdash; the SDK now includes multiple platform versions that you can develop against and each has its own sample code directory. </p>
+
+<h4>Documentation</h4>
+
+<p>The SDK package includes a full set of local documentation. To view it, open the <code>&lt;sdk&gt;/documentation.html</code> file in a web browser. If you are developing in an IDE such as Eclipse, you can also view the reference documentation directly in the IDE. </p>
+
+<p>The most current documentation is always available on the Android Developers site:</p>
+
+<p style="margin-left:2em;"><a href="http://developer.android.com/index.html">http://developer.android.com/</a></p>
+
diff --git a/docs/html/sdk/1.5_r3/installing.jd b/docs/html/sdk/1.5_r3/installing.jd
new file mode 100644
index 0000000..8c3e8ee
--- /dev/null
+++ b/docs/html/sdk/1.5_r3/installing.jd
@@ -0,0 +1,332 @@
+sdk.version=1.5
+sdk.rel.id=3
+sdk.date=April 2009
+
+page.title=Installing the Android SDK
+@jd:body
+
+
+<p>This page describes how to install the Android SDK and set up your
+development environment. If you haven't downloaded the SDK, you can
+do so from the 
+<a href="index.html">Download</a> page. Once you've downloaded
+the SDK, return here.</p>
+
+<p>If you encounter any problems during installation, see the 
+<a href="#installnotes">Installation Notes</a> at the bottom of
+this page.</p>
+
+<h4 style="margin-top">Upgrading?</h4>
+<p>If you have already developed applications using an earlier version
+of the SDK, please read 
+<a href="upgrading.html"><strong>Upgrading the
+SDK</strong></a></b>, instead.
+</p>
+
+
+<h2 id="setup">Preparing for Installation</h2>
+
+<p>Before you begin, take a moment to confirm that your development machine meets the 
+<a href="requirements.html">System Requirements</a>.
+</p>
+
+<p>If you will be developing on Eclipse with the Android Development
+Tools (ADT) Plugin &mdash; the recommended path if you are new to
+Android &mdash; make sure that you have a suitable version of Eclipse
+installed on your computer (3.3 or newer). If you need to install Eclipse, you can
+download it from this location: </p>
+
+<p style="margin-left:2em;"><a href=
+"http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a
+></p>
+
+<p>A Java or RCP version of Eclipse is recommended. </p>
+
+<h2 id="installingsdk">Installing the SDK</h2>
+
+<p>After downloading the SDK, unpack the .zip archive to a suitable location on your machine. 
+By default, the SDK files are unpacked into a directory named 
+<code>android_sdk_<em>&lt;platform</em>&gt;_<em>&lt;release&gt;</em></code>. 
+The directory contains a local copy of the documentation (accessible by opening
+<code>documentation.html</code> in your browser) and the subdirectories 
+<code>tools/</code>, <code>add-ons/</code>, <code>platforms/</code>, and others. Inside
+each subdirectory of <code>platforms/</code> you'll find <code>samples/</code>, which includes
+code samples that are specific to each version of the platform.</p>
+
+<p>Make a note of the name and location of the unpacked SDK directory on your system &mdash; you 
+will need to refer to the SDK directory later, when setting up the Android plugin or when 
+using the SDK tools.</p>
+
+<p>Optionally, you may want to add the location of the SDK's primary <code>tools</code> directory 
+to your system PATH. The primary <code>tools/</code> directory is located at the root of the 
+SDK folder. Adding <code>tools</code> to your path lets you run Android Debug Bridge (adb) and 
+the other command line <a href="{@docRoot}guide/developing/tools/index.html">tools</a> without 
+needing to supply the full path to the tools directory. </p>
+<ul>
+    <li>On Linux, edit your <code>~/.bash_profile</code> or <code>~/.bashrc</code> file. Look
+    for a line that sets the PATH environment variable and add the
+    full path to the <code>tools/</code> directory to it. If you don't 
+    see a line setting the path, you can add one:</li>
+
+    <ul><code>export PATH=${PATH}:<em>&lt;your_sdk_dir&gt;</em>/tools</code></ul>
+
+    <li>On a Mac, look in your home directory for <code>.bash_profile</code> and
+    proceed as for Linux. You can create the <code>.bash_profile</code> if 
+    you haven't already set one up on your machine. </li>
+
+    <li>On Windows, right-click on My Computer, and select Properties.  
+  Under the Advanced tab, hit the Environment Variables button, and in the
+  dialog that comes up, double-click on Path (under System Variables). Add the full path to the 
+  <code>tools/</code> directory to the path. </li>
+  </ul>
+
+<p>Note that, if you update your SDK in the future, you 
+should remember to update your PATH settings to point to the new location, if different.</p>
+
+<p>If you will be using the Eclipse IDE as your development environment,
+the next section describes how to install the Android Development Tools plugin and set up Eclipse. 
+If you choose not to use Eclipse, you can 
+develop Android applications in an IDE of your choice and then compile, debug and deploy using
+the tools included in the SDK (skip to <a href="#next">Next Steps</a>).</p>
+
+
+<h2 id="installingplugin">Installing the ADT Plugin for Eclipse</h2>
+
+<p>Android offers a custom plugin for the Eclipse IDE, called Android
+Development Tools (ADT), that is designed to give you a powerful,
+integrated environment in which to build Android applications. It
+extends the capabilites of Eclipse to let you quickly set up new Android
+projects, create an application UI, add components based on the Android
+Framework API, debug your applications using the Android SDK tools, and even export
+signed (or unsigned) APKs in order to distribute your application.</p>
+
+<p>In general, using Eclipse with ADT is a highly recommended
+approach to Android development and is the fastest way to get started.
+(If you prefer to work in an IDE other than Eclipse,
+you do not need to install Eclipse or ADT, instead, you can directly
+use the SDK tools to build and debug your application.)</p>
+
+<p>Once you have Eclipse installed, as described in <a href="#setup">Preparing for 
+Installation</a>, follow the steps below to
+download the ADT plugin and install it in your respective Eclipse
+environment. </p>
+
+<table style="font-size:100%">
+<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr>
+<tr>
+<td width="45%">
+<!-- 3.3 steps -->
+<ol>
+    <li>Start Eclipse, then select <strong>Help</strong> &gt; <strong>Software Updates</strong> 
+&gt; <strong>Find and Install...</strong>. </li>
+    <li>In the dialog that appears, select <strong>Search for new features to install</strong> 
+and click <strong>Next</strong>. </li>
+    <li>Click <strong>New Remote Site</strong>. </li>
+    <li>In the resulting dialog box, enter a name for the remote site (e.g. "Android Plugin") and 
+    enter the URL:
+        <pre>https://dl-ssl.google.com/android/eclipse/</pre>
+        <p>If you have trouble aqcuiring the plugin, try using "http" in the URL,
+        instead of "https" (https is preferred for security reasons).</p>
+        <p>Click <strong>OK</strong>.</p> </li>
+    <li>You should now see the new site added to the search list (and checked).
+        Click <strong>Finish</strong>. </li>
+    <li>In the subsequent Search Results dialog box, select the checkbox for the
+    "Android Plugin".
+    This will select the nested tools: "Android DDMS" and "Android Development Tools". 
+    Click <strong>Next</strong>.</li>
+    <li>Read and accept the license agreement, then click <strong>Next</strong>. </li>
+    <li>On the following Installation window, click <strong>Finish</strong>. </li>
+    <li>The ADT plugin is not digitally signed. Accept the installation anyway
+        by clicking <strong>Install All</strong>. </li>
+    <li>Restart Eclipse. </li>
+</ol>
+
+</td>
+<td>
+
+<!-- 3.4 steps -->
+<ol>
+    <li>Start Eclipse, then select <strong>Help</strong> &gt; <strong>Software Updates...</strong>.</li>
+    <li>In the dialog that appears, click the <strong>Available Software</strong> tab. </li>
+    <li>Click <strong>Add Site...</strong> </li>
+    <li>Enter the Location:
+      <pre>https://dl-ssl.google.com/android/eclipse/</pre>
+        <p>If you have trouble aqcuiring the plugin, try using "http" in the Location URL,
+        instead of "https" (https is preferred for security reasons).</p>   
+      <p>Click <strong>OK</strong>.</p></li>
+    <li>Back in the Available Software view, you should see the plugin listed by the URL,
+    with "Developer Tools" nested within it. Select the checkbox next to 
+      Developer Tools and click <strong>Install...</strong></li>
+    <li>On the subsequent Install window, "Android DDMS" and "Android Development Tools"
+    should both be checked. Click <strong>Next</strong>. </li>
+    <li>Read and accept the license agreement, then click <strong>Finish</strong>.</li>
+    <li>Restart Eclipse. </li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+<p>Now modify your Eclipse preferences to point to the Android SDK directory:</p>
+<ol>
+    <li>Select <strong>Window</strong> &gt; <strong>Preferences...</strong> to open the Preferences
+        panel (Mac: <strong>Eclipse</strong> &gt; <strong>Preferences</strong>).</li>
+    <li>Select <strong>Android</strong> from the left panel. </li>
+    <li>For the <em>SDK Location</em> in the main panel, click <strong>Browse...</strong> and 
+locate your downloaded SDK directory. </li>
+    <li>Click <strong>Apply</strong>, then <strong>OK</strong>.</li>
+</ol>
+
+<p>Done! If you haven't encountered any problems, then you're ready to
+begin developing Android applications. See the 
+<a href="#next">Next Steps</a> section for suggestions on how to start. </p>
+
+
+<h3 id="troubleshooting">Troubleshooting ADT Installation</h3>
+<p> 
+If you are having trouble downloading the ADT plugin after following the steps above, here are 
+some suggestions: </p>
+
+<ul>
+  <li>If Eclipse can not find the remote update site containing the ADT plugin, try changing 
+  the remote site URL to use http, rather than https. That is, set the Location for the remote site to:
+  <pre>http://dl-ssl.google.com/android/eclipse/</pre></li>
+  <li>If you are behind a firewall (such as a corporate firewall), make
+  sure that you have properly configured your proxy settings in Eclipse.
+  In Eclipse 3.3/3.4, you can configure proxy information from the main
+  Eclipse menu in <strong>Window</strong> (on Mac, <strong>Eclipse</strong>) &gt; 
+  <strong>Preferences</strong> &gt; <strong>General</strong> &gt; 
+  <strong>Network Connections</strong>.</li>
+</ul>
+<p> 
+If you are still unable to use Eclipse to download the ADT plugin as a remote update site, you 
+can download the ADT zip file to your local machine and manually install the it:
+</p>
+<ol>
+  <li><a href="{@docRoot}sdk/adt_download.html">Download the ADT zip file</a> (do not unpack it).</li>
+  <li>Follow steps 1 and 2 in the default install instructions (above).</li>
+  <li>In Eclipse 3.3, click <strong>New Archive Site...</strong>. <br/>
+      In Eclipse 3.4, click <strong>Add Site...</strong>, then <strong>Archive...</strong></li>
+  <li>Browse and select the downloaded zip file.</li>
+  <li>Follow the remaining procedures, above, starting from steps 5.</li>
+</ol>
+<p>To update your plugin once you've installed using the zip file, you will have to 
+follow these steps again instead of the default update instructions.</p>
+
+<h4>Other install errors</h4>
+
+<p>Note that there are features of ADT that require some optional 
+Eclipse components (for example, WST). If you encounter an error when 
+installing ADT, your Eclipse installion might not include these components. 
+For information about how to quickly add the necessary components to your 
+Eclipse installation, see the troubleshooting topic 
+<a href="{@docRoot}guide/appendix/faq/troubleshooting.html#installeclipsecomponents">ADT 
+Installation Error: "requires plug-in org.eclipse.wst.sse.ui"</a>.</p>
+
+<h4>For Linux users</h4>
+<p>If you encounter this error when installing the ADT Plugin for Eclipse: 
+<pre>
+An error occurred during provisioning.
+Cannot connect to keystore.
+JKS</pre>
+<p>
+...then your development machine lacks a suitable Java VM. Installing Sun
+Java 6 will resolve this issue and you can then reinstall the ADT
+Plugin.</p>
+
+
+<h2 id="next">Next Steps</h2>
+<p>Once you have completed installation, you are ready to
+begin developing applications. Here are a few ways you can get started: </p>
+
+<p><strong>Learn about Android</strong></p>
+<ul>
+  <li>Take a look at the <a href="{@docRoot}guide/index.html">Dev
+  Guide</a> and the types of information it provides</li>
+  <li>Read an introduction to Android as a platform in <a
+  href="{@docRoot}guide/basics/what-is-android.html">What is
+  Android?</a></li>
+  <li>Learn about the Android framework and how applications run on it in
+  <a href="{@docRoot}guide/topics/fundamentals.html">Application
+  Fundamentals</a></li>
+  <li>Take a look at the Android framework API specification in the <a
+  href="{@docRoot}reference/packages.html">Reference</a> tab</li>
+</ul>
+
+<p><strong>Explore the SDK</strong></p>
+<ul>
+  <li>Get an overview of the <a
+  href="{@docRoot}guide/developing/tools/index.html">development
+  tools</a> that are available to you</li>
+  <li>Read how to develop <a
+  href="{@docRoot}guide/developing/eclipse-adt.html">in Eclipse/ADT</a> or
+  <a href="{@docRoot}guide/developing/other-ide.html">in other IDEs</a>
+  </li>
+</ul>
+
+<p><strong>Explore some code</strong></p>
+<ul>
+  <li>Set up a <a href="{@docRoot}guide/tutorials/hello-world.html">Hello
+  World application</a> (highly recommended, especially for Eclipse users)</li>
+  <li>Follow the <a href="{@docRoot}guide/tutorials/notepad/index.html">
+  Notepad Tutorial</a> to build a full Android application </li>
+  <li>Create a new project for one of the other sample applications
+  included in <code><em>&lt;sdk&gt;</em>/platforms/<em>&lt;platfrom&gt;</em>/samples</code>, 
+  then compile and run it in your development environment</li>
+</ul>
+
+<p><strong>Visit the Android developer groups</strong></p>
+<ul>
+  <li>Take a look at the <a
+  href="{@docRoot}community/index.html">Community</a> tab to see a list of
+  Android developers groups. In particular, you might want to look at the
+  <a href="http://groups.google.com/group/android-developers">Android
+  Developers</a> group to get a sense for what the Android developer
+  community is like.</li>
+</ul>
+
+
+<h2 id="installnotes">Installation Notes</h2>
+
+<h3>Ubuntu Linux Notes</h3>
+
+<ul>
+  <li>If you need help installing and configuring Java on your
+    development machine, you might find these resources helpful: 
+    <ul>
+      <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/Java </a></li>
+      <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/JavaInstallation</a></li>
+    </ul>
+  </li>
+  <li>Here are the steps to install Java and Eclipse, prior to installing
+  the Android SDK and ADT Plugin.
+    <ol>
+      <li>If you are running a 64-bit distribution on your development
+      machine, you need to install the <code>ia32-libs</code> package using
+      <code>apt-get:</code>:
+      <pre>apt-get install ia32-libs</pre>
+      </li>
+      <li>Next, install Java: <pre>apt-get install sun-java6-bin</pre></li>
+      <li>The Ubuntu package manager does not currently offer an Eclipse 3.3
+      version for download, so we recommend that you download Eclipse from
+      eclipse.org (<a
+      href="http://www.eclipse.org/downloads/">http://www.eclipse.org/
+      downloads/</a>). A Java or RCP version of Eclipse is recommended.</li>
+      <li>Follow the steps given in previous sections to install the SDK 
+      and the ADT plugin. </li>
+    </ol>
+  </li>
+</ul>
+
+<h3>Other Linux Notes</h3>
+
+<ul>
+  <li>If JDK is already installed on your development computer, please
+  take a moment to make sure that it meets the version requirements listed
+  in the <a href="{@docRoot}sdk/{@sdkCurrent}/requirements.html">System Requirements</a>.
+  In particular, note that some Linux distributions may include JDK 1.4 or Gnu
+  Compiler for Java, both of which are not supported for Android development.</li>
+</ul>
+
+
+
diff --git a/docs/html/sdk/1.5_r3/requirements.jd b/docs/html/sdk/1.5_r3/requirements.jd
new file mode 100644
index 0000000..4ed38a7
--- /dev/null
+++ b/docs/html/sdk/1.5_r3/requirements.jd
@@ -0,0 +1,39 @@
+page.title=System Requirements
+@jd:body
+
+<p>The sections below describe the system and software requirements for developing Android applications using the Android SDK tools included in Android <?cs var:sdk.version ?> SDK, Release <?cs var:sdk.rel.id ?>. </p>
+
+<h3>Supported Operating Systems</h3>
+<ul>
+  <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
+  <li>Mac OS X 10.4.8 or later (x86 only)</li>
+  <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+</ul>
+
+<h3>Supported Development Environments</h3>
+<ul>
+  <li>Eclipse IDE
+    <ul>
+      <li><a href="http://www.eclipse.org/downloads/">Eclipse</a> 3.3 (Europa), 3.4 (Ganymede)
+        <ul>
+        <li>Recommended Eclipse IDE packages: Eclipse IDE for Java EE Developers, Eclipse IDE for Java Developers, Eclipse for RCP/Plug-in Developers</li>
+        <li>Eclipse <a href="http://www.eclipse.org/jdt">JDT</a> plugin (included in most Eclipse IDE packages) </li>
+        <li>Eclipse Classic IDE package is not supported.</li>
+        </ul>
+      </li>     
+      <li><a href="http://java.sun.com/javase/downloads/index.jsp">JDK 5 or JDK 6</a> (JRE alone is not sufficient)</li>
+      <li><a href="installing.html#installingplugin">Android Development Tools plugin</a> (optional)</li>
+      <li><strong>Not</strong> compatible with Gnu Compiler for Java (gcj)</li>
+    </ul>
+  </li>
+  <li>Other development environments or IDEs
+    <ul>
+      <li><a href="http://java.sun.com/javase/downloads/index.jsp">JDK 5 or JDK 6</a> (JRE alone is not sufficient)</li>
+      <li><a href="http://ant.apache.org/">Apache Ant</a> 1.6.5 or later for Linux and Mac, 1.7 or later for Windows</li>
+      <li><strong>Not</strong> compatible with Gnu Compiler for Java (gcj)</li>
+    </ul>
+  </li>
+</ul>
+
+<p class="note"><strong>Note:</strong> If JDK is already installed on your development computer, please take a moment to make sure that it meets the version requirements listed above. In
+particular, note that some Linux distributions may include JDK 1.4 or Gnu Compiler for Java, both of which are not supported for Android development. </p>
\ No newline at end of file
diff --git a/docs/html/sdk/1.5_r3/upgrading.jd b/docs/html/sdk/1.5_r3/upgrading.jd
new file mode 100644
index 0000000..a0a62a2
--- /dev/null
+++ b/docs/html/sdk/1.5_r3/upgrading.jd
@@ -0,0 +1,395 @@
+page.title=Upgrading the SDK
+sdk.version=1.5_r3
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+  <h2>Upgrading the SDK</h2>
+  <ul>
+    <li>The Android 1.5 SDK uses a new project structure and a new ADT plugin (ADT 0.9). </li>
+    <li>To move existing projects into the SDK, you must make some minor changes in your 
+    development environment.</li>
+    <li>The new ADT plugin (ADT 0.9) <em>is not compatible</em> with projects created in previous SDKs.</li>
+    <li>You need to uninstall your existing ADT plugin, before installing ADT 0.9.</li>
+  </ul>
+
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#Install">Install the SDK</a></li>
+    <li><a href="#UpdateAdt">Update Your Eclipse ADT Plugin</a></li>
+    <li><a href="#UpdateYourProjects">Update Your Projects</a>
+      <ol>
+        <li><a href="#EclipseUsers">Eclipse Users</a></li>
+        <li><a href="#AntUsers">Ant Users</a></li>
+      </ol>
+    </li>
+    <li><a href="#MigrateYourApplications">Migrate Your Applications</a>
+      <ol><li><a href="#FutureProofYourApps">Future-proof your apps</a></li></ol>
+    </li>
+  </ol>
+  
+  <h2>Migrating references</h2>
+  <ol>
+    <li><a href="{@docRoot}sdk/api_diff/3/changes.html">Android 1.5 API Differences</a></li>
+    <li><a 
+href="http://android-developers.blogspot.com/2009/04/future-proofing-your-apps.html">Future-Proofing
+Your Apps &raquo;</a></li>
+    <li><a 
+href="http://android-developers.blogspot.com/2009/04/ui-framework-changes-in-android-15.html">UI 
+framework changes in Android 1.5 &raquo;</a></li>
+  </ol>
+
+</div>
+</div>
+
+<p>This document describes how to move your development environment and existing
+Android applications from an Android 1.0 or 1.1 SDK to the Android 1.5 SDK.
+If you are migrating applications from an SDK older than 1.0, please also read the upgrading
+document available in the Android 1.0 SDK package.</p>
+
+<p>There are several compelling reasons to upgrade, such as new SDK tools
+that make developing more efficient and new APIs that allow you to expand the feature-set
+of your applications. However, even if you or your applications don't require these enhancements,
+it's important that you upgrade to ensure that your applications run properly on the 
+Android 1.5 platform.</p>
+
+<p>The Android 1.5 platform will soon be deployable to devices around the world.
+If you have already released Android applications to the public, you should
+test the forward-compatibility of your applications on the latest version of the platform
+as soon as possible. It's unlikely that you'll encounter breakage in your applications, but
+in the interest of maintaining the best user experience, you should take no risks.
+So, please install the new Android SDK and test your applications on Android 1.5.</p>
+
+<p>For more information on new SDK features and system changes, 
+see the <a href="{@docRoot}sdk/android-1.5.html">Android 1.5 Version Notes</a>.</p>
+
+
+<h2 id="Install">Install the SDK</h2>
+
+<p>If you haven't yet downloaded the SDK, <a href="index.html">download from here</a> 
+and unpack it into a safe location.</p>
+
+<p><strong>Before you begin:</strong>
+If you had previously setup your PATH variable to point to the SDK tools directory, 
+then you need to update it to point to the new SDK. For example, for a 
+<code>.bashrc</code> or <code>.bash_profile</code> file:</p>
+<pre>export PATH=$PATH:<em>&lt;your_sdk_dir></em>/tools</pre>
+
+<p>If you don't use Eclipse for development,
+skip to <a href="#updateYourProjects">Update Your Projects</a>.</p>
+
+
+<h2 id="UpdateAdt">Update Your Eclipse ADT Plugin</h2>
+
+<p><em>If you installed ADT-0.9_pre with the early look 1.5 SDK, there have been
+additional changes, so please continue with this guide and update to the final ADT 0.9.</em></p>
+
+<p>A new ADT plugin (version 0.9) is required for the Android 1.5 SDK.
+Because the component structure has been changed since Android 1.1, 
+the Android 1.5 SDK does not work with ADT 0.8 (or older) and previously installed SDKs will not
+work with ADT 0.9. However, the Android 1.5 SDK includes an Android 1.1 SDK image that you
+can build against while using ADT 0.9. </p>
+
+<p class="note">For information about using different system images (such as Android 1.1) 
+while running this SDK, see Developing <a href="{@docRoot}guide/developing/eclipse-adt.html">
+In Eclipse, with ADT</a> or <a href="{@docRoot}guide/developing/other-ide.html">In 
+Other IDEs</a>, as appropriate for your development environment.</p>
+
+<p>In order to upgrade your Eclipse IDE to use the new 0.9 ADT, follow the steps below
+for your respective version of Eclipse.</p>
+
+<h3 id="uninstallAdt">Uninstall your previous ADT plugin</h3>
+
+<p>You must uninstall your existing ADT plugin (0.8 or older). If you do not uninstall it,
+you will get a conflict with the Android Editors when installing the new ADT.
+(If you have already installed ADT-0.9_pre with the early look 1.5 SDK, you can skip this
+uninstall procedure and continue to <a href="#installAdt">Install the 0.9 ADT plugin</a>).</p>
+
+<table style="font-size:100%">
+<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr>
+<tr>
+<td width="50%">
+<!-- 3.3 steps -->
+<ol>
+    <li>Select <strong>Help</strong> &gt; <strong>Software Updates</strong> &gt; 
+      <strong>Manage Configuration</strong>. </li>
+    <li>Expand the list in the left panel to reveal the installed tools.</li>
+    <li>Right-click "Android Editors" and click <strong>Uninstall</strong>. Click <strong>OK</strong> 
+    to confirm.</li>
+    <li>Restart Eclipse. 
+      <p>(Do not uninstall "Android Development Tools".)</p></li>
+</ol>
+</td>
+<td>
+<!-- 3.4 steps -->
+<ol>
+    <li>Select <strong>Help</strong> &gt; <strong>Software Updates</strong>.</li>
+    <li>Select the <strong>Installed Software</strong> tab.</li>
+    <li>Select "Android Editors". Click <strong>Uninstall</strong>.</li>
+    <li>In the next window, be sure "Android Editors" is checked, then click <strong>Finish</strong>
+    to uninstall.</li>
+    <li>Restart Eclipse.
+      <p>(Do not uninstall "Android Development Tools".)</p></li>
+</ol>
+</td>
+</tr>
+</table>
+
+
+<h3 id="installAdt">Install the 0.9 ADT plugin</h3>
+
+<p>Only install the new plugin once you've completed the procedure to
+<a href="#uninstallAdt">Uninstall your previous ADT plugin</a>.</p>
+
+<table style="font-size:100%">
+<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr>
+<tr>
+<td width="50%">
+<!-- 3.3 steps -->
+<ol>
+    <li>Select <strong>Help</strong> &gt; <strong>Software Updates</strong> &gt; 
+      <strong>Find and Install</strong>. </li>
+    <li>Select <strong>Search for new features to install</strong>.</li>
+    <li>Select the Android plugin entry by checking the box next to it, 
+      then click <strong>Finish</strong>.
+      <p>(Your original entry for the plugin should still be here. If not, see the guide
+      to <a href="installing.html#installingplugin">Installing the ADT Plugin</a>.)
+      </p></li>
+    <li>In the results, expand the entry for the Android plugin and
+      be sure that "Developer Tools" is checked, then click <strong>Next</strong>.
+      (This will install "Android DDMS" and "Android Development Tools".)</li>
+    <li>Read and accept the license agreement, then click <strong>Next</strong>.
+    <li>In the next window, click <strong>Finish</strong> to start installation.</li>
+    <li>The ADT plugin is not digitally signed. Accept the installation anyway by clicking 
+    <strong>Install All</strong>.</li>
+    <li>Restart Eclipse.</li>
+</ol>
+</td>
+<td>
+<!-- 3.4 steps -->
+<ol>
+    <li>Select <strong>Help</strong> &gt; <strong>Software Updates</strong>.</li>
+    <li>Select the <strong>Available Software</strong> tab.</li>
+    <li>Expand the entry for the Andriod plugin (may be listed as the location URL)
+      and select "Developer Tools" by checking the box next to it, then click 
+      <strong>Install</strong>.</li>
+    <li>On the next window, "Android DDMS" and "Android Development Tools" 
+    should both be checked. Click <strong>Finish</strong>.</li>
+    <li>Restart Eclipse.</li>
+</ol>
+</td>
+</tr>
+</table>
+
+<p>If you encounter problems, ensure your ADT is fully uninstalled and then
+follow the guide to 
+<a href="installingplugin">Installing the ADT Plugin
+for Eclipse</a>.</p>
+
+<h3 id="updateEclipsePrefs">Update your Eclipse SDK Preferences</h3>
+
+<p>The last step is to update your Eclipse preferences to point to the new SDK directory:</p>
+    <ol>
+      <li>Select <strong>Window</strong> > <strong>Preferences</strong> to open the Preferences 
+      panel (Mac: <strong>Eclipse</strong> > <strong>Preferences</strong>).</li>
+      <li>Select <strong>Android</strong> from the left panel.</li>
+      <li>For the <em>SDK Location</em> in the main panel, click <strong>Browse</strong> 
+      and locate your SDK directory.</li>
+      <li>Click <strong>Apply</strong>, then <strong>OK</strong>.</li>
+    </ol>
+
+
+<h2 id="UpdateYourProjects">Update Your Projects</h2>
+
+<p>You will now need to update any and all Android projects that you have
+developed using a previous version of the Android SDK.</p>
+
+
+<h3 id="EclipseUsers">Eclipse users</h3>
+
+<p>If you use Eclipse to develop applications, use the following procedure to 
+update each project:</p>
+
+<ol>
+  <li>Right-click on the individual project (in the Package Explorer)
+   and select <strong>Properties</strong>.</li>
+  <li>In the properties, open the Android panel and select a "build target" to compile 
+    against. This SDK offers the Android 1.1 and Android 1.5 platforms to choose from. When 
+    you are initially updating your projects to the new SDK, we recommend that you select a build 
+    target with the Android 1.1 platform. Click <strong>Apply</strong>, then 
+    <strong>OK</strong>.</li>
+</ol>
+
+<p>The new plugin creates a <code>gen/</code> folder in your project, in which it puts the 
+<code>R.java</code> file
+and all automatically generated AIDL java files. If you get an error such as 
+<code>The type R is already defined</code>, 
+then you probably need to delete your old <code>R.java</code> or your old auto-generated
+AIDL Java files in the <code>src/</code> folder.
+(This <em>does not</em> apply to your own hand-crafted parcelable AIDL java files.)</p>
+
+<p>Note that, with the Android 1.5 SDK, there is a new process for running 
+applications in the Android Emulator. 
+Specifically, you must create an Android Virtual Device (AVD) before you can launch an instance
+of the Emulator. Before attempting to run your applications with the new SDK, 
+please continue with the section below to 
+<a href="#MigrateYourApplications">Migrate Your Applications</a>.</p>
+
+
+<h3 id="AntUsers">Ant users</h3>
+
+<p>If you build your projects using the Ant tool (rather than with Eclipse), note the 
+following changes with the new SDK tools.</p>
+
+<h4>build.xml has changed</h4>
+
+<p>You must re-create your <code>build.xml</code> file.</p>
+
+<p>If you had customized your <code>build.xml</code>, first make a copy of it:</p>
+
+<pre>
+$ cd <em>my-project</em>
+$ cp build.xml build.xml.old
+</pre>
+
+<p>Now use the new <code>android</code> tool (located in <code><em>your_sdk</em>/tools/</code>) 
+to create a new <code>build.xml</code> that references 
+a specific platform target:</p>
+
+<pre>$ android update project --path /path/to/my-project --target 1</pre>
+
+<p>The "target" corresponds to an Android platform library (including any add-ons, such as 
+Google APIs) that you would like to build your project against. You can view a list of available 
+targets (and their corresponding integer ID) with the command, <code>android list targets</code>. 
+When you are initially updating your projects to the new SDK, we recommend that you select the 
+first target ("1"), which uses the Android 1.1 platform library.</p>
+
+<p>A <code>gen/</code> folder will be created the first time you build and your <code>R.java</code> and
+your AIDL Java files will be generated in here. You <strong>must</strong> remove
+the old <code>R.java</code> and old auto-generated AIDL java files from the 
+<code>src/</code> folder. (This
+does not apply to your own hand-crafted parcelabe AIDL java files.)</p>
+
+<p class="note"><strong>Note:</strong> The "activitycreator" tool has been replaced 
+by the new "android" tool. For information on creating new projects with the android tool,
+see the documentation about <a href="{@docRoot}guide/developing/other-ide.html">Developing 
+In Other IDEs</a>.</p>
+
+<p>Note that, with the Android 1.5 SDK, there is a new process for running 
+applications in the Android Emulator. 
+Specifically, you must create an Android Virtual Device (AVD) before you can launch an instance
+of the Emulator. Before attempting to run your applications with the new SDK, 
+please continue with the section below to 
+<a href="#MigrateYourApplications">Migrate Your Applications</a>.</p>
+
+
+<h2 id="MigrateYourApplications">Migrate Your Applications</h2>
+
+<p>After you have completed the process above to <a href="#UpdateYourProjects">Update Your 
+Projects</a>, you are strongly encouraged to run each of your applications in an instance
+of the emulator running the Android 1.5 system image. It's possible (however, unlikely) 
+that you'll encounter some breakage in your application when you run your applications on
+the Android 1.5 system image. Whether you believe your application will be affected by 
+platform changes or not, it's very important that you test the application's 
+forward-compatibility on Android 1.5.</p>
+
+<p>To test forward-compatibility, simply run your existing application (as-is) on an Android
+Emulator that's running the Android 1.5 system image. The following procedure will guide
+you through the process to running your existing applications on an emulator. <em>Please read
+the following guide completely before you begin</em>.</p>
+
+<p>To test your application on an emulator running Android 1.5:</p>
+<ol>
+  <li><a href="#UpdateYourProjects">Update Your Project</a> (you should have done this 
+  already, in the section above).</li>
+  <li>Run your existing project, as-is, on an emulator running the Android 1.5 system image.
+    <p>As mentioned in the guide to <a href="#UpdateYourProjects">Update Your Projects</a>, 
+    you should have selected a "build
+    target" of "1", which compiles your application against the Android 1.1 system image, so there
+    should be no new errors in your code.</p>
+    <p>Eclipse users: follow the 
+    <a href="{@docRoot}guide/developing/eclipse-adt.html#Running">Eclipse guide to 
+    Running Your Application</a>.</p>
+    <p>Ant users: follow the 
+    <a href="{@docRoot}guide/developing/other-ide.html#Running">Ant guide to 
+    Running Your Application</a>
+    <p>During the procedure to Running Your Application, select a "deployment target" 
+    for the AVD that includes the Android 1.5 platform. 
+    If your application utilizes the Google Maps APIs (i.e.,
+    MapView), be certain to select a target that includes the Google APIs.</p>
+    <p>Once you complete the procedures to run your application in your respective environment,
+    linked above, return here.</p>
+  </li>
+  <li>With your application running in the emulator, perform all regular testing on the application
+  to ensure that it functions normally (in both landscape and portrait orientations).</li>
+</ol>
+
+<p>Chances are, your application runs just fine on the Android 1.5 platform &mdash; 
+new devices will be able to safely install and run your application and
+current users who update their devices will be able to continue using your application as usual.
+However, if something doesn't work the way you expect, then you might need to revisit
+your project and make any necessary changes to your code.</p>
+
+<p>You can check for code breakages caused by API changes by opening your project 
+in Eclipse, changing the "build target" to one using the Android 1.5 platform,
+and see where the ADT identifies errors in your code.</p>
+
+
+<h3 id="FutureProofYourApps">Future-proof your apps</h3>
+
+<p>There have been several API additions made for this release, but there have been
+very few actual API <em>changes</em>. Only a couple (relatively unused) elements 
+have been removed and a few have been deprecated, so your applications written with the 
+Android 1.1 system library should work just fine. However, 
+your application is more likely to encounter problems on Android 1.5
+if it performs any of the following:</p>
+
+<ul>
+  <li>Uses internal APIs. That is, APIs that are not officially supported
+  and not available in the reference documentation. Any un-official APIs are always subject
+  to change (which is why they're un-official) and some have indeed changed.
+  </li>
+  <li>Directly manipulates system settings. There are some settings (such as
+  GPS, data roaming, bluetooth and others) that used to be writable by 
+  applications but have been changed so that they can only be explicitly modified by the user
+  through the system settings. Refer to {@link android.provider.Settings.Secure}
+  to see which settings are now secured and cannot be directly changed by your application.
+  </li>
+  <li>Uses View hierarchies that are unreasonably deep (more than 10 or so levels) or 
+  broad (more than 30 total). View hierarchies this big have always been troublesome, but 
+  Android 1.5 is much more efficient at exposing this and your application may crash.
+  </li>
+  <li>Makes assumptions about the available hardware. With new support for soft keyboards,
+  not all devices will have full QWERTY keyboards on the hardware. So if your application
+  listens for special keypress events that only occur on a keypad, then your application
+  should degrade gracefully when there is no keyboard available.
+  </li>
+  <li>Performs its own layout orientation changes based on the acceletometer (or via other
+  sensors). Some devices running Android 1.5 will automatically rotate the orientation
+  (and all devices have the option to turn on auto-rotation), so if your application also
+  attempts to rotate the orientation, it can result in strange behavior. In addition, if your
+  application uses the accelerometer to detect shaking and you do not want to rotate the 
+  orientation, then you should lock the current orientation with 
+  <a href="{@docRoot}guide/topics/manifest/activity-element.html#screen">android:screenOrientation</a>.
+  </li>
+</ul>
+
+<p>Please read our blog post on <a 
+href="http://android-developers.blogspot.com/2009/04/future-proofing-your-apps.html">Future-Proofing
+Your Apps</a> for more information on the issues mentioned above.</p>
+
+<p>For information
+about other changes made to Android 1.5, refer to the following documents:</p>
+<ul>
+  <li><a href="{@docRoot}sdk/api_diff/3/changes.html">Android 1.5 API Differences</a></li>
+  <li><a href="{@docRoot}sdk/android-1.5.html#api-changes">Android 1.5 Version Notes</a></li> 
+  <li><a 
+href="http://android-developers.blogspot.com/2009/04/ui-framework-changes-in-android-15.html">UI 
+framework changes in Android 1.5 &raquo;</a></li>
+</ul>
+
+<p>If you have additional trouble updating your code, visit the 
+<a href="http://groups.google.com/group/android-developers">Android Developers Group</a>
+to seek help from other Android developers.</p>
diff --git a/docs/html/sdk/RELEASENOTES.jd b/docs/html/sdk/RELEASENOTES.jd
index f3a1951..03eeb4b 100644
--- a/docs/html/sdk/RELEASENOTES.jd
+++ b/docs/html/sdk/RELEASENOTES.jd
@@ -5,6 +5,75 @@
 releases. For the latest known issues, please ensure that you're viewing this
 page at <a href="http://developer.android.com/sdk/RELEASENOTES.html">http://developer.android.com/sdk/RELEASENOTES.html</a>.</p>
 
+<h2 id="1.5_r3">Android 1.5 SDK, Release 3</h2>
+
+<p>Provides an updated Android 1.5 system image that includes permissions
+fixes, as described below, and a new application &mdash; an IME for Japanese 
+text input. Also provides the same set of developer tools included in the 
+previous SDK, but with bug fixes and several new features.</p>
+
+<h3>Permissions Fixes</h3>
+
+<p>The latest version of the Android platform, deployable to 
+Android-powered devices, includes fixes to the permissions-checking
+in certain areas of the framework. Specifically, the Android system
+now properly checks and enforces several existing permissions where it
+did not do so in the previous release. Because of these changes in 
+enforcement, you are strongly encouraged to test your application 
+against the new Android 1.5 system image included in this SDK, to ensure 
+that it functions normally. </p>
+
+<p>In particular, if your application uses any of the system areas listed below,
+you should add the required permissions to the application's manifest and then
+test the areas of your code that depend on the permission-protected services.
+Even if you believe your application does not use the permissions-protected
+services, you should compile and test your application under the latest platform
+version to ensure that users will not encounter problems when using your
+application. </p>
+
+<p>The changes to permissions are as follows:</p>
+
+<ul>
+<li>When an application requests access to device camera (through
+android.hardware.camera), the <code>CAMERA</code> permission check is now
+properly enforced. </li>
+<li>When an application requests access to device audio capture (through
+android.media.MediaRecorder), the <code>RECORD_AUDIO</code> permission check is
+now properly enforced.</li>
+</ul>
+
+<p>For more information, see the issue described in the oCert advisory
+below:</p>
+
+<p style="margin-left: 2em;"><a href="http://www.ocert.org/advisories/ocert-2009-011.html">http://www.ocert.org/advisories/ocert-2009-011.html</a> </p>
+
+<h3>Resolved Issues, Changes</h3>
+
+<ul>
+<li>The SDK includes a new version of the Google APIs add-on. The add-on
+provides an updated com.google.android.maps external library that fixes compile
+errors related to certain classes such as GeoPoint. For information about the
+Google APIs add-on and the library it provides, see:
+
+<p style="margin-left:2em;"><a
+href="http://code.google.com/android/add-ons/google-apis">http://code.google.com/android/add-ons/google-apis</a> </p></li>
+
+<li>The SDK add-on architecture now lets device manufacturers specify a USB
+Vendor ID in their add-ons. 
+<li>The <code>android</code> tool provides a new command that scans SDK add-ons
+for their USB Vendor IDs and makes them available to adb (OS X and Linux
+versions of the SDK only). The command is  <code>android update adb</code>. On
+Windows versions of the SDK, a custom USB driver is included that supports the
+"Google" and "HTC" Vendor IDs, which allow adb to recognize G1 and HTC
+Magic devices. For other devices, contact the device manufacturer 
+to obtain a USB driver, especially if you have an SDK add-on that defines 
+a new USB Vendor ID.</li>
+<li>The telephony, sensor, and geo fix issues in the emulator are now
+fixed.</li>
+<li>When you use adb to uninstall an upgraded application, the Android system
+now properly restores any permissions that had already been granted to the
+previous (downgrade) version of the application</li>
+</ul>
 
 <h2 id="1.5_r2">Android 1.5 SDK, Release 2</h2>
 
diff --git a/docs/html/sdk/android-1.5.jd b/docs/html/sdk/android-1.5.jd
index addd6446..748f3ee 100644
--- a/docs/html/sdk/android-1.5.jd
+++ b/docs/html/sdk/android-1.5.jd
@@ -125,6 +125,7 @@
 	<li>Dialer</li>
 	<li>Email</li>
 	<li>Gallery</li>
+	<li>IME for Japanese text input</li>
 	<li>Messaging</li>
 	<li>Music</li>
 	<li>Settings</li>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 38db6f8..2ac7688 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -1,4 +1,5 @@
-sdk.redirect=1.1_r1
+sdk.redirect=true
+
 @jd:body
 
 
diff --git a/docs/html/sdk/ndk/1.5-r1/index.jd b/docs/html/sdk/ndk/1.5_r1/index.jd
similarity index 81%
rename from docs/html/sdk/ndk/1.5-r1/index.jd
rename to docs/html/sdk/ndk/1.5_r1/index.jd
index 3d3137c..7ccbbcd 100644
--- a/docs/html/sdk/ndk/1.5-r1/index.jd
+++ b/docs/html/sdk/ndk/1.5_r1/index.jd
@@ -1,32 +1,35 @@
 ndk=true
 ndk.version=1.5
 ndk.rel.id=1
-ndk.date=May 2009
+ndk.date=June 2009
 
 ndk.win_download=android-ndk-1.5_r1-windows.zip
-ndk.win_bytes=22450814
-ndk.win_checksum=7b7836f705ec7e66225794edda34000f
+ndk.win_bytes=22500667
+ndk.win_checksum=e5c53915903d8b81f3e2ea422e2e2717
 
 ndk.mac_download=android-ndk-1.5_r1-darwin-x86.zip
-ndk.mac_bytes=17165450
-ndk.mac_checksum=214ccfd704c0307609fbabeb7bf86acc
+ndk.mac_bytes=17215303
+ndk.mac_checksum=1931f0e182798a4c98924fd87380b5b8
 
 ndk.linux_download=android-ndk-1.5_r1-linux-x86.zip
-ndk.linux_bytes=15976032
-ndk.linux_checksum=808fd4d6a7e45f76d546ba04ab9ef060
-
-ndk.linux_64_download=android-ndk-1.5_r1-linux-x86_64.zip
-ndk.linux_64_bytes=18112300
-ndk.linux_64_checksum=f8664c187b3ae077bcfe2b44294d0758
+ndk.linux_bytes=16025885
+ndk.linux_checksum=80a4e14704ca84c21bf1824cb25fbd8b
 
 page.title=Android 1.5 NDK, Release 1
 @jd:body
 
-<h2>What is the NDK?</h2>
+<h2 id="overview">What is the Android NDK?</h2>
 
-<p>The Android 1.5 NDK provides tools that allow Android application developers
-to embed and deploy native code within their Android applications. It
-provides:</p>
+<p>The Android NDK provides tools that allow Android application developers
+to embed components that make use of native code in their Android applications.
+</p>
+
+<p>Android applications run in the Dalvik virtual machine. The NDK allows 
+developers to implement parts of their applications using native-code languages 
+such as C and C++. This can provide benefits to certain classes of applications, 
+in the form of reuse of existing code and in some cases increased speed.</p>
+
+<p>The NDK provides:</p>
 
 <ul>
 <li>A set of tools and build files used to generate native code libraries from C
@@ -35,18 +38,21 @@
 files (.apks) that can be deployed on Android devices</li>
 <li>A set of native system headers and libraries that will be supported in all
 future versions of the Android platform, starting from Android 1.5 </li>
+<li>Documentation, samples, and tutorials</li>
 </ul>
 
-<p>This release of the NDK release supports the ARMv5TE machine instruction set
-and provides stable headers for libc (the C library), libm (the Math library)
-and the JNI interface.</p>
+<p>This release of the NDK supports the ARMv5TE machine instruction set
+and provides stable headers for libc (the C library), libm (the Math library), 
+the JNI interface, and other libraries.</p>
 
-<p>Using the NDK may not be relevant for all Android applications. As a
-developer, you will need to balance its benefits (faster execution) and its
-drawbacks (no portability, JNI overhead, no access to system libraries, and
-difficult debugging). Typical good candidates for the NDK are CPU-intensive
-operations that don't allocate too much memory, such as signal processing,
-physics simulation, custom bytecode/instruction interpreters, and so on.</p>
+<p>The NDK will not benefit most applications. As a developer, you will need 
+to balance its benefits against its drawbacks; notably, using native code does 
+not result in an automatic performance increase, but does always increase 
+application complexity. Typical good candidates for the NDK are self-contained,
+CPU-intensive operations that don't allocate much memory, such as signal processing,
+physics simulation, and so on. Simply re-coding a method to run in C usually does 
+not result in a large performance increase. The NDK can, however, can be 
+an effective way to reuse a large corpus of existing C/C++ code.</p>
 
 <p>Please note that the NDK <em>does not</em> enable you to develop native-only
 applications. Android's primary runtime remains the Dalvik virtual machine.</p>
@@ -64,8 +70,11 @@
 
 <ul>
 <li>libc (C library) headers</li>
-<li>libm (Math library) headers</li>
+<li>libm (math library) headers</li>
 <li>JNI interface headers</li>
+<li>libz (Zlib compression) headers</li>
+<li>liblog (Android logging) header</li>
+<li>A Minimal set of headers for C++ support</li>
 </ul>
 
 <p>The NDK also provides a build system that lets you work efficiently with your
@@ -97,6 +106,22 @@
 defines the native sources you want to compile</li>
 <li>APPLICATION-MK.TXT &mdash; describes the use of the Application.mk file,
 which describes the native sources required by your Android application</li>
+<li>HOWTO.TXT &mdash; information about common tasks associated with NDK 
+development.</li>
+<li>SYSTEM-ISSUES.TXT &mdash; known issues in the Android system images 
+that you should be aware of, if you are developing using the NDK. </li>
+<li>STABLE-APIS.TXT &mdash; a complete list of the stable APIs exposed
+by headers in the NDK.</li>
+</ul>
+
+<p>Additionally, the package includes detailed information about the "bionic"
+C library provided with the Android platform that you should be aware of, if you
+are developing using the NDK. You can find the documentation in the 
+<code>&lt;ndk&gt;/docs/system/libc/</code> directory:</p>
+
+<ul>
+<li>OVERVIEW.TXT &mdash; provides an overview of the "bionic" C library and the 
+features it offers.</li>
 </ul>
 
 <h4>Sample applications</h4>
@@ -142,13 +167,14 @@
   <li>For all development platforms, GNU Make 3.81 or later is required. Earlier
 versions of GNU Make might work but have not been tested.</li>
   <li>For Windows, a recent release of <a
-href="http://www.cygwin.com">Cygwin</a> is required.</li>
+href="http://www.cygwin.com">Cygwin</a>, including both the gmake and gcc 
+packages, is required. </li>
 </ul>
 
 <h4>Android platform compatibility</h4>
 <ul>
   <li>The native libraries created by the Android NDK can only be used on
-devices running the Android 1.5 platform version or later. This is due to subtle
+devices running the Android 1.5 platform version or later. This is due to 
 toolchain and ABI related changes that make the native libraries incompatible
 with 1.0 and 1.1 system images.</li>
   <li>For this reason, you should use native libraries produced with the NDK in
diff --git a/docs/html/sdk/older_releases.jd b/docs/html/sdk/older_releases.jd
index 3c2bbd4..febccd04 100644
--- a/docs/html/sdk/older_releases.jd
+++ b/docs/html/sdk/older_releases.jd
@@ -26,6 +26,12 @@
      <th>Description</td>
    </tr>
    <tr>
+     <td><a href="{@docRoot}sdk/1.5_r1/index.html">Android 1.5 SDK, Release 2</a></td>
+     <td style="text-align:center;">Android 1.5<br>Android 1.1</td>
+     <td><em>May 2009</em></td>
+     <td>Replaced by Android 1.5 SDK, Release 3. <em><a href="RELEASENOTES.html#1.5_r2">Release notes</a></em></td>
+   </tr>
+   <tr>
      <td><a href="{@docRoot}sdk/1.5_r1/index.html">Android 1.5 SDK, Release 1</a></td>
      <td style="text-align:center;">Android 1.5<br>Android 1.1</td>
      <td><em>April 2009</em></td>
diff --git a/docs/html/sdk/preview/features.html b/docs/html/sdk/preview/features.html
deleted file mode 100644
index a2f085c..0000000
--- a/docs/html/sdk/preview/features.html
+++ /dev/null
@@ -1,191 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-
-  <head>
-    <title>Redirecting...</title>
-    <meta http-equiv="refresh" content="0;url=/sdk/android-1.5-highlights.html">
-    <link href="/assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
-  </head>
-
-<body class="gc-documentation">
-<a name="top"></a>
-
-  <div id="header">
-      <div id="headerLeft">
-          <a href="/index.html" tabindex="-1"><img
-              src="/assets/images/bg_logo.png" alt="Android Developers" /></a>
-          <ul class="sdk">
-              <li id="home-link"><a href="/index.html">
-                  <span>Home</span></a></li>
-              <li id="sdk-link"><a href="/sdk/1.5_r1/index.html"><span>SDK</span></a></li>
-              <li id="guide-link"><a href="/guide/index.html"
-                                  onClick="return loadLast('guide')"><span>Dev Guide</span></a></li>
-              <li id="reference-link"><a href="/reference/packages.html" 
-                                  onClick="return loadLast('reference')"><span>Reference</span></a></li>
-              <li><a href="http://android-developers.blogspot.com"><span>Blog</span></a></li>
-              <li id="community-link"><a href="/community/index.html"><span>Community</span></a></li>
-          </ul>
-      </div>
-      <div id="headerRight">
-          <div id="headerLinks">
-            <!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
-            <span class="text">
-              <!-- &nbsp;<a href="#">English</a> | -->
-              <a href="http://www.android.com">Android.com</a>
-            </span>
-          </div>
-  <div id="search" >
-      <div id="searchForm">
-          <form accept-charset="utf-8" class="gsc-search-box" 
-                onsubmit="return submit_search()">
-            <table class="gsc-search-box" cellpadding="0" cellspacing="0"><tbody>
-                <tr>
-                  <td class="gsc-input">
-                    <input id="search_autocomplete" class="gsc-input" type="text" size="33" autocomplete="off" 
-                      title="search developer docs" name="q"
-                      value="search developer docs" 
-                      onFocus="search_focus_changed(this, true)" 
-                      onBlur="search_focus_changed(this, false)" 
-                      onkeydown="return search_changed(event, true, '/')" 
-                      onkeyup="return search_changed(event, false, '/')" />
-                  <div id="search_filtered_div" class="no-display">
-                      <table id="search_filtered" cellspacing=0>
-                      </table>
-                  </div>
-                  </td>
-                  <td class="gsc-search-button">
-                    <input type="submit" value="Search" title="search" id="search-button" class="gsc-search-button" />
-                  </td>
-                  <td class="gsc-clear-button">
-                    <div title="clear results" class="gsc-clear-button">&nbsp;</div>
-                  </td>
-                </tr></tbody>
-              </table>
-          </form>
-      </div><!-- searchForm -->
-  </div><!-- search -->
-      </div><!-- headerRight -->
-  </div><!-- header -->
-
-
-  <div class="g-section g-tpl-240" id="body-content">
-    <div class="g-unit g-first not-resizable" id="side-nav">
-      <div id="devdoc-nav">
-<ul>
-  <li>
-    <h2>Current SDK Release</h2>
-    <ul>
-      <li><a href="/sdk/1.5_r2/index.html">Download</a></li>
-      <li><a href="/sdk/1.5_r2/installing.html">Installing</a></li>
-      <li><a href="/sdk/1.5_r2/upgrading.html">Upgrading</a></li>
-      <li><a href="/sdk/1.5_r2/requirements.html">System Requirements</a></li>
-    </ul>
-    <ul>
-      <li><a href="/sdk/terms.html">SDK Terms and Conditions</a></li>
-      <li><a href="/sdk/RELEASENOTES.html">SDK Release Notes</a></li>
-    </ul>
-  <li>
-    <h2>System Image Version Notes</h2>
-    <ul>
-      <li><a href="/sdk/android-1.5.html">Android 1.5 Version Notes</a></li>
-      <li><a href="/sdk/android-1.1.html">Android 1.1 Version Notes</a></li>
-    </ul>
-  </li>
-  <li>
-    <h2>Previous SDK Releases</h2>
-    <ul>
-      <li><a href="/sdk/1.1_r1/index.html">Android 1.1 SDK, r1</a></li>
-      <li><a href="/sdk/1.0_r2/index.html">Android 1.0 SDK, r2</a></li>
-      <li><a href="/sdk/older_releases.html">Other Releases</a></li>
-    </ul>
-  </li>
-</ul>
-
-<script type="text/javascript">
-<!--
-    buildToggleLists();
-//-->
-</script>
-      </div>
-    </div> <!-- end side-nav -->
-
-
-
-<div class="g-unit">
-  <div id="jd-content">
-    <p>Redirecting to 
-    <a href="/sdk/1.5_r1/index.html">
-    /sdk/android-1.5-highlights.html
-    </a></p>
-
-</div><!-- end jd-content -->
-
-
-
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content --> 
-
-</body>
-</html>
-
-
-
diff --git a/docs/html/sdk/preview/features.jd b/docs/html/sdk/preview/features.jd
new file mode 100644
index 0000000..43856de
--- /dev/null
+++ b/docs/html/sdk/preview/features.jd
@@ -0,0 +1,6 @@
+sdk.redirect=true
+sdk.redirect.path=android-1.5-highlights.html
+
+@jd:body
+
+
diff --git a/docs/html/sdk/preview/index.jd b/docs/html/sdk/preview/index.jd
index cb699e9..1e6b26b 100644
--- a/docs/html/sdk/preview/index.jd
+++ b/docs/html/sdk/preview/index.jd
@@ -1,5 +1,5 @@
 sdk.redirect=true
-@jd:body
 
+@jd:body
 
 
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 2079dd8..22d6f43 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -1,16 +1,42 @@
-
+<?cs if:!sdk.redirect ?>
 <ul>
   <li><?cs 
    if:android.whichdoc != "online" ?>
     <h2>Android <?cs var:sdk.version ?> SDK, r<?cs var:sdk.rel.id ?></h2><?cs 
    else ?>
-    <h2>Current SDK Release</h2><?cs 
+    <h2><span class="en">Current SDK Release</span>
+        <span class="de">Aktuelle SDK-Version</span>
+        <span class="es">Versión actual del SDK</span>
+        <span class="fr">Version actuelle du SDK</span>
+        <span class="it">Release SDK attuale</span>
+        <span class="ja">現在リリースされている SDK</span>
+        <span class="zh-CN">当前的 SDK 版本</span>
+        <span class="zh-TW">目前 SDK 發行版本</span>
+    </h2><?cs 
    /if ?>
     <ul><?cs 
      if:android.whichdoc == "online" ?>
-      <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/index.html">Download</a></li><?cs 
+      <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/index.html">
+          <span class="en">Download</span>
+          <span class="de">Herunterladen</span>
+          <span class="es">Descargar</span>
+          <span class="fr">Téléchargement</span>
+          <span class="it">Download</span>
+          <span class="ja">ダウンロード</span>
+          <span class="zh-CN">下载</span>
+          <span class="zh-TW">下載</span>
+         </a></li><?cs 
      /if ?>
-      <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/installing.html">Installing</a></li>
+      <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/installing.html">
+          <span class="en">Installing</span>
+          <span class="de">Installieren</span>
+          <span class="es">Instalación</span>
+          <span class="fr">Installation</span>
+          <span class="it">Installazione</span>
+          <span class="ja">インストール</span>
+          <span class="zh-CN">安装</span>
+          <span class="zh-TW">安裝</span>
+      </a></li>
       <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/upgrading.html">Upgrading</a></li>
       <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/requirements.html">System Requirements</a></li>
     </ul>
@@ -20,14 +46,37 @@
     </ul><?cs 
  if:android.whichdoc == "online" ?>
   <li>
-    <h2>System Image Version Notes</h2>
+    <h2><span class="en">System Image Version Notes</span>
+        <span class="de">Versionshinweise zum Systemabbild</span>
+        <span class="es">Notas de la versión de System Image</span>
+        <span class="fr">Notes de version de l'image système</span>
+        <span class="it">Note sulla versione dell'immagine <br />di sistema</span>
+        <span class="ja">システム イメージ バージョンに<br />関する注意事項</span>
+        <span class="zh-CN">系统图片版本说明</span>
+        <span class="zh-TW">系統影像版本資訊</span>
+    </h2>
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/android-1.5.html">Android 1.5 Version Notes</a></li>
       <li><a href="<?cs var:toroot ?>sdk/android-1.1.html">Android 1.1 Version Notes</a></li>
     </ul>
   </li>
   <li>
-    <h2>Previous SDK Releases</h2>
+    <h2>Native Development Tools</h2>
+    <ul>
+      <li><a href="<?cs var:toroot ?>sdk/ndk/1.5_r1/index.html">Android 1.5 NDK, r1</a></li>
+    </ul>
+  </li>
+  <li>
+     <h2>
+        <span class="en">Previous SDK Releases</span>
+        <span class="de">Frühere SDK-Releases</span>
+        <span class="es">Versiones anteriores del SDK</span>
+        <span class="fr">Anciennes versions du SDK</span>
+        <span class="it">Release SDK precedenti</span>
+        <span class="ja">SDK の過去のリリース</span>
+        <span class="zh-CN">以前的 SDK 版本</span>
+        <span class="zh-TW">較舊的 SDK 發行版本</span>
+    </h2>
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/1.1_r1/index.html">Android 1.1 SDK, r1</a></li>
       <li><a href="<?cs var:toroot ?>sdk/1.0_r2/index.html">Android 1.0 SDK, r2</a></li>
@@ -40,5 +89,7 @@
 <script type="text/javascript">
 <!--
     buildToggleLists();
+    changeNavLang(getLangPref());
 //-->
-</script>
\ No newline at end of file
+</script>
+<?cs /if ?>
\ No newline at end of file
diff --git a/docs/html/sitemap-intl.txt b/docs/html/sitemap-intl.txt
new file mode 100644
index 0000000..ded0554
--- /dev/null
+++ b/docs/html/sitemap-intl.txt
@@ -0,0 +1,12 @@
+http://developer.android.com/ja/sdk/1.5_r3/installing.html
+http://developer.android.com/ja/community/index.html
+http://developer.android.com/ja/index.html
+http://developer.android.com/ja/guide/publishing/versioning.html
+http://developer.android.com/ja/guide/publishing/app-signing.html
+http://developer.android.com/ja/guide/publishing/preparing.html
+http://developer.android.com/ja/guide/tutorials/hello-world.html
+http://developer.android.com/ja/guide/topics/fundamentals.html
+http://developer.android.com/ja/guide/index.html
+http://developer.android.com/ja/guide/basics/what-is-android.html
+http://developer.android.com/ja/guide/developing/other-ide.html
+http://developer.android.com/ja/guide/developing/eclipse-adt.html
diff --git a/docs/html/videos/index.jd b/docs/html/videos/index.jd
new file mode 100644
index 0000000..c9c88cf
--- /dev/null
+++ b/docs/html/videos/index.jd
@@ -0,0 +1,338 @@
+videos=true
+page.title=Videos
+@jd:body
+
+<script src="http://swfobject.googlecode.com/svn/trunk/swfobject/swfobject.js" type="text/javascript"></script>

+<script src="{@docRoot}assets/jquery-history.js" type="text/javascript"></script>
+<script type="text/javascript">
+// for debugging in FF, so other browsers ignore the console commands.
+var console;
+if (!console) console = { 'log': function() {} };
+
+/* This 'playlist' object defines the playlist IDs for each tab.
+ * Each name inside 'playlist' corresponds to class names for the tab that the playlists belong to (eg: "googleioTab" and "googleioBox" divs).
+ * Each string in 'ids' is the ID of a YouTube playlist that belongs in the corresponding tab.
+ */
+var playlists = {
+  'googleio' : {
+    'ids': ["734A052F802C96B9"]
+  },
+  'about' : {
+    'ids': ["D7C64411AF40DEA5","611F8C5DBF49CEC6"]
+  },
+  'developertips' : {
+    'ids': ["43E15866EF0033A2"]
+  },
+  'developersandbox' : {
+    'ids': ["77426907BBAD558E"]
+  }
+};
+
+/* Some playlists include the title in the description meta-data, so we need to account for this when building the thumbnail lists, so we don't show the title twice
+ * This string is read via indexOf(), so multiple IDs need only be comma-separated in this string.
+ */
+var playlistsWithTitleInDescription = "734A052F802C96B9";
+
+/* This 'featured' object defines the Feature Videos list. 
+ * Each playlist ID is paired with a custom video description.
+ */
+var featured = {
+// How to Make your Android UI Fast..
+  'N6YdwzAvwOA' : "Make your user interface fast, with more efficient AdapterViews, better bitmap scaling, faster redrawing, ViewStub layouts, fewer Views, and more.", 
+// Coding for Life: Battery Life
+  'OUemfrKe65c' : "Learn what kinds of operations consume the most battery and how you can reduce your usage, with tips for parsing and zipping data, using wakelocks, and running a Service.",
+// How Do I Code Thee?
+  'GARMe7Km_gk' : "If you'd like to augment your Android applications with pieces written in JavaScript or native code, watch this video."
+};
+

+/* When an event on the browser history occurs (back, forward, load),
+ * load the video found in the URL hash 
+ */

+$(window).history(function(e, hash) {

+  if (location.href.indexOf("#v=") != -1) {

+    videoId = location.href.split("#v=");

+    clickVideo(videoId[1]); // click the link with a matching class

+  }

+});
+
+/* Load a video into the player box.
+ * @param id        The YouTube video ID
+ * @param title     The video title to display in the player box (character escaped)
+ * @param autoplay  Whether to automatically play the video 
+ */
+function loadVideo(id, title, autoplay) {
+  if($("." + id).hasClass("noplay")) {
+  	console.log("noplay");
+  	autoplay = false;
+  	$("." + id).removeClass("noplay");
+  }
+  swfobject.embedSWF('http://www.youtube.com/v/' + id + '&rel=1&border=0&fs=1&autoplay=' + 
+      (autoplay?1:0), 'player', '500', '334', '9.0.0', false, false, {allowfullscreen: 'true'});
+  $("#videoPlayerTitle").html("<h2>" + unescape(title) + "</h2>");
+  

+  $.history.add('v=' + id); // add the current video to the browser history
+  document.getElementById("doc-content").scrollTop = 0; // scroll the window to the top 
+}
+
+/* Draw all videos from a playlist into a 'videoPreviews' list
+ * @param data  The feed data returned from the youtube request
+ */
+function renderPlaylist(data) {  
+  var MAX_DESC_LENGTH = 390; // the length at which we will trim the description
+  var feed = data.feed;
+  var entries = feed.entry || [];
+  var playlistId = feed.yt$playlistId.$t;
+  
+  var ul = $('<ul class="videoPreviews" />');
+  
+  // Loop through each entry (each video) and add it to the 'videoPreviews' list
+  for (var i = 0; i < entries.length; i++) {
+    var entry = entries[i];
+    
+    var title = entry.title.$t;
+    var id = entry.media$group.yt$videoid.$t;
+    var thumbUrl = entry.media$group.media$thumbnail[0].url;
+    var fullDescription = entry.media$group.media$description.$t;
+    var playerUrl = entry.media$group.media$content[0].url;
+      
+    // Check whether this playlist includes the video title inside the description meta-data, so we can remove it
+    if (playlistsWithTitleInDescription.indexOf(playlistId) != -1) {
+      var lines = fullDescription.split("\n");
+      // If the first line includes the first 17 chars from the title, let's use the title from the desciption instead (because it's a more complete title)
+      // This accounts for, literally, "Google I/O 2009 -", which is (so far) the min AND max for properly identifying a title in the only playlist with titles in the description
+      if (lines[0].indexOf(title.slice(0,16)) != -1) {  
+			h3Title = "<h3>" + lines[0] + "</h3>"; 	
+      	if (lines[2].length < 30) lines = lines.slice(3);  // also, if the second line is very short (the speaker name), slice it out too
+      	else lines = lines.slice(1);  // otherwise, slice after the first line
+      }
+      fullDescription = lines.join("");
+    } 
+    
+    var shortDescription = fullDescription.substr(0, MAX_DESC_LENGTH);
+    shortDescription += shortDescription.length == MAX_DESC_LENGTH ? "..." : ""; // add ellipsis if we've chopped the description
+  
+    var img = $('<img src="' + thumbUrl + '" width="120" height="90"/>');
+    var a = $('<a class="' + id + '" href="#" onclick="loadVideo(\'' + id + '\',\'' + escape(title) + '\',true); return setSelected(this);" />');
+    var pShortDescription = $('<p class="short">' + shortDescription + '</p>');
+    var pFullDescription = $('<p class="full">' + fullDescription + '</p>');
+    var h3Title = "<h3>" + title + "</h3>";
+    var pToggle = "<p class='toggle'><a href='#' onclick='return toggleDescription(this)'><span class='more'>more</span><span class='less'>less</span></a></p>";
+    var li = $('<li/>');
+    
+    li.append(a);
+    a.append(img).append(h3Title).append(pShortDescription);
+    
+    // Add the full description and "more/less" toggle, if necessary
+    if (fullDescription.length > MAX_DESC_LENGTH) {
+    	a.append(pFullDescription);
+    	li.append(pToggle);
+    }
+    
+    ul.append(li);
+  }
+  
+  // Now add the 'videoPreviews' list to the page, and be sure we put it in the right tab
+  // This is the part that allows us to put multiple playlists in one tab
+  for (var x in playlists) {
+    var ids = playlists[x].ids;
+    for (var i in ids) {
+      if (ids[i] == playlistId) {
+        $("#"+x+"Box").append(ul);
+        break;
+      }
+    }
+  }  
+}
+
+/* Draw a featured video into the existing 'videoPreviews' list 
+ * @param data  The video data returned from the youtube request
+ */
+function renderFeatured(data) {  
+  var MAX_TITLE_LENGTH = 48;
+  var entry = data.entry || [];
+  var id = entry.media$group.yt$videoid.$t;
+  var description = featured[id];
+  var title = entry.title.$t;
+  var thumbUrl = entry.media$group.media$thumbnail[0].url;
+  var playerUrl = entry.media$group.media$content[0].url;
+  
+  var ellipsis = title.length > MAX_TITLE_LENGTH ? "..." : "";
+    
+  var h3Title = "<h3>"+ title.substr(0,MAX_TITLE_LENGTH) + ellipsis + "</h3>";
+  var img = $('<img src="' + thumbUrl + '" width="120" height="90"/>');
+  var p = $('<p>' + description + '</p>');
+  var a = $('<a class="' + id + '" href="#" onclick="loadVideo(\'' + id + '\',\'' + title + '\',true); return setSelected(this);" />');
+  var li = $("<li/>");
+  
+  a.append(h3Title).append(img).append(p);
+  li.append(a);
+
+  $("#mainBodyRight .videoPreviews").append(li);
+}
+
+/* Request the playlist feeds from YouTube */
+function showPlaylists() {
+  for (var x in playlists) {
+    var ids = playlists[x].ids;
+    for (var i in ids) {
+      var script = "<script type='text/javascript' src='http://gdata.youtube.com/feeds/api/playlists/" 
+      				  + ids[i] + 
+      				  "?v=2&alt=json-in-script&callback=renderPlaylist'><\/script>";
+    	$("body").append(script);
+    }
+  }
+}
+
+/* Request the featured videos from YouTube */
+function showFeatured() {
+  for (var id in featured) {
+    var script = "<script type='text/javascript' src='http://gdata.youtube.com/feeds/api/videos/" 
+    					+ id + 
+    					"?v=2&alt=json-in-script&callback=renderFeatured'><\/script>";
+    $("body").append(script);
+  }
+}
+
+/* Reveal a tab (playlist) box 
+ * @param name  The name of the tab
+ */
+function showBox(name) {
+  $("#"+name+"Box").addClass("selected").siblings().removeClass("selected");
+  $("#"+name+"Tab").addClass("selected").siblings().removeClass("selected");
+  return false;
+}
+
+/* Highlight a video thumbnail, including all duplicates that there may be 
+ * @param link  The link <a> object that was clicked
+ */
+function setSelected(link) {
+  var videoId = $(link).attr("class");
+  if (videoId.indexOf("selected") != -1) {  // this means this video is already selected and playing, so bail out
+    return false;
+  }
+  $(".videoPreviews .selected").removeClass("selected");
+  $("a." + videoId).addClass("selected").each( function (i) {
+  	 if ($(this).is(":hidden")) {
+  	   var boxName = $(this).parent().parent().parent().attr("id").split("Box");
+  	   $("#"+boxName[0]+"Tab a").click();
+  	 }
+  });
+  return false;
+}
+
+/* Reveal and hide the long/short descriptions for a video in the playlist 
+ * @param link  The link <a> object that was clicked 
+ */
+function toggleDescription(link) {
+	var aToggle = $(link);
+	$("span", aToggle).toggle();
+	var aDescription = $(">a", aToggle.parent().parent());
+	$("p.short", aDescription).toggle();
+	$("p.full", aDescription).toggle();
+	if ($("span.less", aToggle).is(":visible")) {
+		aDescription.css("height", "auto");
+	} else {
+		aDescription.css("height", "90px");
+	}
+	return false;
+}
+
+/* Add actions to the page onload event so that we load a video right away */
+addLoadEvent(function () {

+  // if there's a video url in the hash, click that video

+  if (location.href.indexOf("#v=") != -1) {

+    var videoId = location.href.split("#v=");
+    clickVideo(videoId[1]);
+  } else { // otherwise, click the default video
+    clickDefaultVideo();
+  }
+});
+
+
+var clickVideoAttempts = 0; // Used with clickVideo()
+
+/* Click a video in order to load it and select it 
+ * @param videoId  The ID of the video to click
+ */
+function clickVideo(videoId) {
+  if ($("." + videoId).length != 0) {  // if we find the video, click it and return
+   $("." + videoId).addClass("noplay"); // add class to indicate we should NOT autoplay (class removed by loadVideo)

+  	$("." + videoId + ":first").click();
+	 return;
+  } else { // if we don't find it, increment clickVideoAttempts
+	 console.log("video NOT found: " + videoId);
+	 clickVideoAttempts++;
+  }
+    
+  // if we don't find it after 20 attempts (2 seconds), click the first feature video

+  if (clickVideoAttempts > 10) {
+	 console.log("video never found, clicking default...");
+    clickVideoAttempts = 0;
+    clickDefaultVideo();
+  } else { // try again after 100 milliseconds
+	 setTimeout('clickVideo("'+videoId+'")', 100);
+  }
+}
+
+/* Click the default video that should be loaded on page load (the first video in the featured list) */
+function clickDefaultVideo() {
+	if ($("#mainBodyRight .videoPreviews a:first").length != 0) {
+  	var videoId = $("#mainBodyRight .videoPreviews a:first").attr("class");
+    $("." + videoId).addClass("noplay"); // add class to indicate we should NOT autoplay (class removed by loadVideo)

+  	$("." + videoId + ":first").click();
+  	return;
+  } else { // if we don't find it, increment clickVideoAttempts
+	 console.log("default video NOT found");
+	 clickVideoAttempts++;
+  }
+  
+  // if we don't find it after 50 attempts (5 seconds), just fail

+  if (clickVideoAttempts > 50) {
+	  console.log("default video never found...");
+  } else { // try again after 100 milliseconds
+	 	setTimeout('clickDefaultVideo()', 100);
+  }
+}
+</script>
+
+  <div id="mainBodyFixed">
+	
+    <div id="mainBodyLeft" class="videoPlayer" >	
+      <div id="videoPlayerBox">
+        <div id="videoBorder">
+          <div id="videoPlayerTitle"></div>
+          <div id="objectWrapper">
+            <object id="player"></object>
+          </div>
+        </div>
+      </div>
+    </div><!-- end mainBodyLeft -->
+    
+    <div id="mainBodyRight" class="videoPlayer">
+      <h2>Featured Videos</h2>
+      <ul class="videoPreviews"></ul>
+    </div><!-- end mainBodyRight -->
+	  
+    <ul id="videoTabs">
+      <li id="aboutTab" class="selected"><a onclick="return showBox('about');" href="#">About the Platform</a></li>
+      <li id="developertipsTab"><a onclick="return showBox('developertips');" href="#">Developer Tips</a></li>
+      <li id="googleioTab"><a onclick="return showBox('googleio');" href="#">Google I/O Sessions</a></li>
+      <li id="developersandboxTab"><a onclick="return showBox('developersandbox');" href="#">Developer Sandbox</a></li>
+    </ul>
+  	
+    <div id="videos">
+      <div id="aboutBox" class="selected"></div>
+      <div id="developertipsBox"></div>
+      <div id="googleioBox"></div>
+      <div id="developersandboxBox"></div>
+    </div>
+    
+  </div><!-- end mainBodyFixed -->
+  
+<script type="text/javascript">
+// Initialization actions
+showFeatured();            // load featured videos
+showPlaylists();           // load playslists
+</script>
+
+	
\ No newline at end of file
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index df659ef..bb19229 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -30,11 +30,11 @@
     /**
      * Indicates that the bitmap was created for an unknown pixel density.
      *
-     * @see Bitmap#getDensityScale()
-     * @see Bitmap#setDensityScale(float)
+     * @see Bitmap#getDensity()
+     * @see Bitmap#setDensity(int)
      */
-    public static final float DENSITY_SCALE_UNKNOWN = -1.0f;
-
+    public static final int DENSITY_NONE = 0;
+    
     // Note:  mNativeBitmap is used by FaceDetector_jni.cpp
     // Don't change/rename without updating FaceDetector_jni.cpp
     private final int mNativeBitmap;
@@ -45,10 +45,10 @@
     private int mHeight = -1;
     private boolean mRecycled;
 
-    private static volatile Matrix sScaleMatrix;
+    // Package-scoped for fast access.
+    /*package*/ int mDensity = DENSITY_NONE;
 
-    private float mDensityScale = DENSITY_SCALE_UNKNOWN;
-    private boolean mAutoScaling;
+    private static volatile Matrix sScaleMatrix;
 
     /**
      * @noinspection UnusedDeclaration
@@ -70,84 +70,39 @@
     }
 
     /**
-     * <p>Returns the density scale for this bitmap, expressed as a factor of
-     * the default density (160.) For instance, a bitmap designed for
-     * displays with a density of 240 will have a density scale of 1.5 whereas a bitmap
-     * designed for a density of 160 will have a density scale of 1.0.</p>
+     * <p>Returns the density for this bitmap.</p>
      *
-     * <p>The default density scale is {@link #DENSITY_SCALE_UNKNOWN}.</p>
+     * <p>The default density scale is {@link #DENSITY_NONE}.</p>
      *
-     * @return A scaling factor of the default density (160) or {@link #DENSITY_SCALE_UNKNOWN}
+     * @return A scaling factor of the default density (160) or {@link #DENSITY_NONE}
      *         if the scaling factor is unknown.
      *
-     * @see #setDensityScale(float)
-     * @see #isAutoScalingEnabled()
-     * @see #setAutoScalingEnabled(boolean)
+     * @see #setDensity(int)
      * @see android.util.DisplayMetrics#DENSITY_DEFAULT
-     * @see android.util.DisplayMetrics#density
-     * @see #DENSITY_SCALE_UNKNOWN
+     * @see android.util.DisplayMetrics#densityDpi
+     * @see #DENSITY_NONE
      */
-    public float getDensityScale() {
-        return mDensityScale;
+    public int getDensity() {
+        return mDensity;
     }
 
     /**
-     * <p>Specifies the density scale for this bitmap, expressed as a factor of
-     * the default density (160.) For instance, a bitmap designed for
-     * displays with a density of 240 will have a density scale of 1.5 whereas a bitmap
-     * designed for a density of 160 will have a density scale of 1.0.</p>
+     * <p>Specifies the density for this bitmap.  When the bitmap is
+     * drawn to a Canvas that also has a density, it will be scaled
+     * appropriately.</p>
      *
-     * @param densityScale The density scaling factor to use with this bitmap or
-     *        {@link #DENSITY_SCALE_UNKNOWN} if the factor is unknown.
+     * @param density The density scaling factor to use with this bitmap or
+     *        {@link #DENSITY_NONE} if the density is unknown.
      *
-     * @see #getDensityScale()
-     * @see #isAutoScalingEnabled()
-     * @see #setAutoScalingEnabled(boolean)
+     * @see #getDensity()
      * @see android.util.DisplayMetrics#DENSITY_DEFAULT
-     * @see android.util.DisplayMetrics#density
-     * @see #DENSITY_SCALE_UNKNOWN
+     * @see android.util.DisplayMetrics#densityDpi
+     * @see #DENSITY_NONE
      */
-    public void setDensityScale(float densityScale) {
-        mDensityScale = densityScale;
+    public void setDensity(int density) {
+        mDensity = density;
     }
-
-    /**
-     * </p>Indicates whether this bitmap will be automatically be scaled at the
-     * target's density at drawing time. If auto scaling is enabled, this bitmap
-     * will be drawn with the following scale factor:</p>
-     *
-     * <pre>scale = (bitmap density scale factor) / (target density scale factor)</pre>
-     *
-     * <p>Auto scaling is turned off by default. If auto scaling is enabled but the
-     * bitmap has an unknown density scale, then the bitmap will never be automatically
-     * scaled at drawing time.</p>
-     *
-     * @return True if the bitmap must be scaled at drawing time, false otherwise.
-     *
-     * @see #setAutoScalingEnabled(boolean)
-     * @see #getDensityScale()
-     * @see #setDensityScale(float)
-     */
-    public boolean isAutoScalingEnabled() {
-        return mAutoScaling;
-    }
-
-    /**
-     * <p>Enables or disables auto scaling for this bitmap. When auto scaling is enabled,
-     * the bitmap will be scaled at drawing time to accomodate the drawing target's pixel
-     * density. The final scale factor for this bitmap is thus defined:</p>
-     *
-     * <pre>scale = (bitmap density scale factor) / (target density scale factor)</pre>
-     *
-     * <p>If auto scaling is enabled but the bitmap has an unknown density scale, then
-     * the bitmap will never be automatically scaled at drawing time.</p>
-     *
-     * @param autoScalingEnabled True to scale the bitmap at drawing time, false otherwise.
-     */
-    public void setAutoScalingEnabled(boolean autoScalingEnabled) {
-        mAutoScaling = autoScalingEnabled;
-    }
-
+    
     /**
      * Sets the nine patch chunk.
      *
@@ -455,9 +410,8 @@
         canvas.drawBitmap(source, srcR, dstR, paint);
 
         // The new bitmap was created from a known bitmap source so assume that
-        // they use the same density scale
-        bitmap.mDensityScale = source.mDensityScale;
-        bitmap.mAutoScaling = source.mAutoScaling;
+        // they use the same density
+        bitmap.mDensity = source.mDensity;
 
         return bitmap;
     }
@@ -603,65 +557,71 @@
     }
 
     /**
-     * Convenience method that returns the width of this bitmap divided
-     * by the density scale factor.
-     *
-     * @param canvas The Canvas the bitmap will be drawn to.
-     * @return The scaled width of this bitmap, according to the density scale factor.
+     * Convenience for calling {@link #getScaledWidth(int)} with the target
+     * density of the given {@link Canvas}.
      */
     public int getScaledWidth(Canvas canvas) {
-        final float scale = mDensityScale;
-        if (!mAutoScaling || scale < 0) {
-            return getWidth();
-        }
-        return (int)(getWidth() * canvas.getDensityScale() / scale);
+        return scaleFromDensity(getWidth(), mDensity, canvas.mDensity);
     }
 
     /**
-     * Convenience method that returns the height of this bitmap divided
-     * by the density scale factor.
-     *
-     * @param canvas The Canvas the bitmap will be drawn to.
-     * @return The scaled height of this bitmap, according to the density scale factor.
+     * Convenience for calling {@link #getScaledHeight(int)} with the target
+     * density of the given {@link Canvas}.
      */
     public int getScaledHeight(Canvas canvas) {
-        final float scale = mDensityScale;
-        if (!mAutoScaling || scale < 0) {
-            return getHeight();
-        }
-        return (int)(getHeight() * canvas.getDensityScale() / scale);
+        return scaleFromDensity(getHeight(), mDensity, canvas.mDensity);
+    }
+
+    /**
+     * Convenience for calling {@link #getScaledWidth(int)} with the target
+     * density of the given {@link DisplayMetrics}.
+     */
+    public int getScaledWidth(DisplayMetrics metrics) {
+        return scaleFromDensity(getWidth(), mDensity, metrics.densityDpi);
+    }
+
+    /**
+     * Convenience for calling {@link #getScaledHeight(int)} with the target
+     * density of the given {@link DisplayMetrics}.
+     */
+    public int getScaledHeight(DisplayMetrics metrics) {
+        return scaleFromDensity(getHeight(), mDensity, metrics.densityDpi);
     }
 
     /**
      * Convenience method that returns the width of this bitmap divided
      * by the density scale factor.
      *
-     * @param metrics The target display metrics.
+     * @param targetDensity The density of the target canvas of the bitmap.
      * @return The scaled width of this bitmap, according to the density scale factor.
      */
-    public int getScaledWidth(DisplayMetrics metrics) {
-        final float scale = mDensityScale;
-        if (!mAutoScaling || scale < 0) {
-            return getWidth();
-        }
-        return (int)(getWidth() * metrics.density / scale);
+    public int getScaledWidth(int targetDensity) {
+        return scaleFromDensity(getWidth(), mDensity, targetDensity);
     }
 
     /**
      * Convenience method that returns the height of this bitmap divided
      * by the density scale factor.
      *
-     * @param metrics The target display metrics.
+     * @param targetDensity The density of the target canvas of the bitmap.
      * @return The scaled height of this bitmap, according to the density scale factor.
      */
-    public int getScaledHeight(DisplayMetrics metrics) {
-        final float scale = mDensityScale;
-        if (!mAutoScaling || scale < 0) {
-            return getHeight();
-        }
-        return (int)(getHeight() * metrics.density / scale);
+    public int getScaledHeight(int targetDensity) {
+        return scaleFromDensity(getHeight(), mDensity, targetDensity);
     }
-
+    
+    /**
+     * @hide
+     */
+    static public int scaleFromDensity(int size, int sdensity, int tdensity) {
+        if (sdensity == DENSITY_NONE || sdensity == tdensity) {
+            return size;
+        }
+        
+        // Scale by tdensity / sdensity, rounding up.
+        return ( (size * tdensity) + (sdensity >> 1) ) / sdensity;
+    }
+    
     /**
      * Return the number of bytes between rows in the bitmap's pixels. Note that
      * this refers to the pixels as stored natively by the bitmap. If you call
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 975bc1a..076cd0c 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -40,7 +40,6 @@
          */
         public Options() {
             inDither = true;
-            inDensity = 0;
             inScaled = true;
         }
 
@@ -80,22 +79,87 @@
         public boolean inDither;
 
         /**
-         * The desired pixel density of the bitmap.
+         * The pixel density to use for the bitmap.  This will always result
+         * in the returned bitmap having a density set for it (see
+         * {@link Bitmap#setDensity(int) Bitmap.setDensity(int)).  In addition,
+         * if {@link #inScaled} is set (which it is by default} and this
+         * density does not match {@link #inTargetDensity}, then the bitmap
+         * will be scaled to the target density before being returned.
+         * 
+         * <p>If this is 0,
+         * {@link BitmapFactory#decodeResource(Resources, int)}, 
+         * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
+         * and {@link BitmapFactory#decodeResourceStream}
+         * will fill in the density associated with the resource.  The other
+         * functions will leave it as-is and no density will be applied.
          *
-         * @see android.util.DisplayMetrics#DENSITY_DEFAULT
-         * @see android.util.DisplayMetrics#density
+         * @see #inTargetDensity
+         * @see #inScreenDensity
+         * @see #inScaled
+         * @see Bitmap#setDensity(int)
+         * @see android.util.DisplayMetrics#densityDpi
          */
         public int inDensity;
 
         /**
-         * </p>If the bitmap is loaded from {@link android.content.res.Resources} and
-         * this flag is turned on, the bitmap will be scaled to match the default
-         * display's pixel density.</p>
+         * The pixel density of the destination this bitmap will be drawn to.
+         * This is used in conjunction with {@link #inDensity} and
+         * {@link #inScaled} to determine if and how to scale the bitmap before
+         * returning it.
+         * 
+         * <p>If this is 0,
+         * {@link BitmapFactory#decodeResource(Resources, int)}, 
+         * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
+         * and {@link BitmapFactory#decodeResourceStream}
+         * will fill in the density associated the Resources object's
+         * DisplayMetrics.  The other
+         * functions will leave it as-is and no scaling for density will be
+         * performed.
+         * 
+         * @see #inDensity
+         * @see #inScreenDensity
+         * @see #inScaled
+         * @see android.util.DisplayMetrics#densityDpi
+         */
+        public int inTargetDensity;
+        
+        /**
+         * The pixel density of the actual screen that is being used.  This is
+         * purely for applications running in density compatibility code, where
+         * {@link #inTargetDensity} is actually the density the application
+         * sees rather than the real screen density.
+         * 
+         * <p>By setting this, you
+         * allow the loading code to avoid scaling a bitmap that is currently
+         * in the screen density up/down to the compatibility density.  Instead,
+         * if {@link #inDensity} is the same as {@link #inScreenDensity}, the
+         * bitmap will be left as-is.  Anything using the resulting bitmap
+         * must also used {@link Bitmap#getScaledWidth(int)
+         * Bitmap.getScaledWidth} and {@link Bitmap#getScaledHeight
+         * Bitmap.getScaledHeight} to account for any different between the
+         * bitmap's density and the target's density.
+         * 
+         * <p>This is never set automatically for the caller by
+         * {@link BitmapFactory} itself.  It must be explicitly set, since the
+         * caller must deal with the resulting bitmap in a density-aware way.
+         * 
+         * @see #inDensity
+         * @see #inTargetDensity
+         * @see #inScaled
+         * @see android.util.DisplayMetrics#densityDpi
+         */
+        public int inScreenDensity;
+        
+        /**
+         * When this flag is set, if {@link #inDensity} and
+         * {@link #inTargetDensity} are not 0, the
+         * bitmap will be scaled to match {@link #inTargetDensity} when loaded,
+         * rather than relying on the graphics system scaling it each time it
+         * is drawn to a Canvas.
          *
-         * </p>This flag is turned on by default and should be turned off if you need
-         * a non-scaled version of the bitmap. In this case,
-         * {@link android.graphics.Bitmap#setAutoScalingEnabled(boolean)} can be used
-         * to properly scale the bitmap at drawing time.</p>
+         * <p>This flag is turned on by default and should be turned off if you need
+         * a non-scaled version of the bitmap.  Nine-patch bitmaps ignore this
+         * flag and are always scaled.
          */
         public boolean inScaled;
 
@@ -236,58 +300,32 @@
      * Decode a new Bitmap from an InputStream. This InputStream was obtained from
      * resources, which we pass to be able to scale the bitmap accordingly.
      */
-    public static Bitmap decodeStream(Resources res, TypedValue value, InputStream is,
-            Rect pad, Options opts) {
+    public static Bitmap decodeResourceStream(Resources res, TypedValue value,
+            InputStream is, Rect pad, Options opts) {
 
         if (opts == null) {
             opts = new Options();
         }
 
-        Bitmap bm = decodeStream(is, pad, opts);
-
-        if (bm != null && res != null && value != null) {
+        if (opts.inDensity == 0 && value != null) {
             final int density = value.density;
-            if (density == TypedValue.DENSITY_NONE) {
-                return bm;
-            }
-            
-            byte[] np = bm.getNinePatchChunk();
-            final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
-
-            if (opts.inDensity == 0) {
-                opts.inDensity = density == TypedValue.DENSITY_DEFAULT ?
-                        DisplayMetrics.DENSITY_DEFAULT : density;
-            }
-            float scale = opts.inDensity / (float) DisplayMetrics.DENSITY_DEFAULT;
-
-            if (opts.inScaled || isNinePatch) {
-                bm.setDensityScale(1.0f);
-                bm.setAutoScalingEnabled(false);
-                // Assume we are going to prescale for the screen
-                scale = res.getDisplayMetrics().density / scale;
-                if (scale != 1.0f) {
-                    // TODO: This is very inefficient and should be done in native by Skia
-                    final Bitmap oldBitmap = bm;
-                    bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f),
-                            (int) (bm.getHeight() * scale + 0.5f), true);
-                    oldBitmap.recycle();
-
-                    if (isNinePatch) {
-                        np = nativeScaleNinePatch(np, scale, pad);
-                        bm.setNinePatchChunk(np);
-                    }
-                }
-            } else {
-                bm.setDensityScale(scale);
-                bm.setAutoScalingEnabled(true);
+            if (density == TypedValue.DENSITY_DEFAULT) {
+                opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
+            } else if (density != TypedValue.DENSITY_NONE) {
+                opts.inDensity = density;
             }
         }
-
-        return bm;
+        
+        if (opts.inTargetDensity == 0 && res != null) {
+            opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
+        }
+        
+        return decodeStream(is, pad, opts);
     }
 
     /**
-     * Decode an image referenced by a resource ID.
+     * Synonym for opening the given resource and calling
+     * {@link #decodeResourceStream}.
      *
      * @param res   The resources object containing the image data
      * @param id The resource id of the image data
@@ -304,7 +342,7 @@
             final TypedValue value = new TypedValue();
             final InputStream is = res.openRawResource(id, value);
 
-            bm = decodeStream(res, value, is, null, opts);
+            bm = decodeResourceStream(res, value, is, null, opts);
             is.close();
         } catch (java.io.IOException e) {
             /*  do nothing.
@@ -316,7 +354,8 @@
     }
 
     /**
-     * Decode an image referenced by a resource ID.
+     * Synonym for {@link #decodeResource(Resources, int, android.graphics.BitmapFactory.Options)}
+     * will null Options.
      *
      * @param res The resources object containing the image data
      * @param id The resource id of the image data
@@ -413,6 +452,39 @@
             bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
         }
 
+        if (bm == null || opts == null) {
+            return bm;
+        }
+        
+        final int density = opts.inDensity;
+        if (density == 0) {
+            return bm;
+        }
+        
+        bm.setDensity(density);
+        final int targetDensity = opts.inTargetDensity;
+        if (targetDensity == 0 || density == targetDensity
+                || density == opts.inScreenDensity) {
+            return bm;
+        }
+        
+        byte[] np = bm.getNinePatchChunk();
+        final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
+        if (opts.inScaled || isNinePatch) {
+            float scale = targetDensity / (float)density;
+            // TODO: This is very inefficient and should be done in native by Skia
+            final Bitmap oldBitmap = bm;
+            bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f),
+                    (int) (bm.getHeight() * scale + 0.5f), true);
+            oldBitmap.recycle();
+
+            if (isNinePatch) {
+                np = nativeScaleNinePatch(np, scale, outPadding);
+                bm.setNinePatchChunk(np);
+            }
+            bm.setDensity(targetDensity);
+        }
+        
         return bm;
     }
 
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index da73597..8ecbfbd 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -20,6 +20,7 @@
 import android.text.SpannedString;
 import android.text.SpannableString;
 import android.text.GraphicsOperations;
+import android.util.DisplayMetrics;
 
 import javax.microedition.khronos.opengles.GL;
 
@@ -47,11 +48,12 @@
     // optional field set by the caller
     private DrawFilter  mDrawFilter;
 
+    // Package-scoped for quick access.
+    /*package*/ int mDensity = DisplayMetrics.DENSITY_DEFAULT;
+    
     // Used by native code
     @SuppressWarnings({"UnusedDeclaration"})
     private int         mSurfaceFormat;
-    @SuppressWarnings({"UnusedDeclaration"})
-    private float       mDensityScale = 1.0f;
 
     /**
      * Construct an empty raster canvas. Use setBitmap() to specify a bitmap to
@@ -76,8 +78,9 @@
         throwIfRecycled(bitmap);
         mNativeCanvas = initRaster(bitmap.ni());
         mBitmap = bitmap;
-        mDensityScale = bitmap.getDensityScale();
-        if (mDensityScale == Bitmap.DENSITY_SCALE_UNKNOWN) mDensityScale = 1.0f;
+        final int density = bitmap.mDensity;
+        mDensity = density == Bitmap.DENSITY_NONE
+                ? DisplayMetrics.DENSITY_DEFAULT : density;
     }
     
     /*package*/ Canvas(int nativeCanvas) {
@@ -132,8 +135,9 @@
 
         native_setBitmap(mNativeCanvas, bitmap.ni());
         mBitmap = bitmap;
-        mDensityScale = bitmap.getDensityScale();
-        if (mDensityScale == Bitmap.DENSITY_SCALE_UNKNOWN) mDensityScale = 1.0f;
+        final int density = bitmap.mDensity;
+        mDensity = density == Bitmap.DENSITY_NONE
+                ? DisplayMetrics.DENSITY_DEFAULT : density;
     }
     
     /**
@@ -172,44 +176,34 @@
     public native int getHeight();
 
     /**
-     * <p>Returns the density scale for this Canvas' backing bitmap, expressed as a
-     * factor of the default density (160dpi.) For instance, a bitmap designed for
-     * 240dpi displays will have a density scale of 1.5 whereas a bitmap
-     * designed for 160dpi will have a density scale of 1.0.</p>
+     * <p>Returns the density for this Canvas' backing bitmap.</p>
      *
-     * <p>The default density scale is {@link Bitmap#DENSITY_SCALE_UNKNOWN}.</p>
+     * <p>The default density scale is {@link Bitmap#DENSITY_NONE}.</p>
      *
      * @return A scaling factor of the default density (160dpi) or
-     *        {@link Bitmap#DENSITY_SCALE_UNKNOWN} if the scaling factor is unknown.
+     *        {@link Bitmap#DENSITY_NONE} if the scaling factor is unknown.
      *
-     * @see #setDensityScale(float)
-     * @see Bitmap#getDensityScale() 
+     * @see #setDensity(int)
+     * @see Bitmap#getDensity() 
      */
-    public float getDensityScale() {
-        if (mBitmap != null) {
-            return mBitmap.getDensityScale();
-        }
-        return mDensityScale;
+    public int getDensity() {
+        return mDensity;
     }
 
     /**
-     * <p>Specifies the density scale for this Canvas' backing bitmap, expressed as a
-     * factor of the default density (160dpi.) For instance, a bitmap designed for
-     * 240dpi displays will have a density scale of 1.5 whereas a bitmap
-     * designed for 160dpi will have a density scale of 1.0.</p>
+     * <p>Specifies the density for this Canvas' backing bitmap.
      *
-     * @param densityScale The density scaling factor to use with this bitmap or
-     *        {@link Bitmap#DENSITY_SCALE_UNKNOWN} if the factor is unknown.
+     * @param density The density scaling factor to use with this bitmap or
+     *        {@link Bitmap#DENSITY_NONE} if the factor is unknown.
      *
-     * @see #getDensityScale()
-     * @see Bitmap#setDensityScale(float) 
+     * @see #getDensity()
+     * @see Bitmap#setDensity(int) 
      */
-    public void setDensityScale(float densityScale) {
+    public void setDensity(int density) {
         if (mBitmap != null) {
-            mBitmap.setDensityScale(densityScale);
+            mBitmap.setDensity(density);
         }
-        mDensityScale = densityScale;
-        if (mDensityScale == Bitmap.DENSITY_SCALE_UNKNOWN) mDensityScale = 1.0f;
+        mDensity = density;
     }
 
     // the SAVE_FLAG constants must match their native equivalents
@@ -945,12 +939,17 @@
     /**
      * Draw the specified bitmap, with its top/left corner at (x,y), using
      * the specified paint, transformed by the current matrix.
-     * Note: if the paint contains a maskfilter that generates a mask which
+     * 
+     * <p>Note: if the paint contains a maskfilter that generates a mask which
      * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
      * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
      * Thus the color outside of the original width/height will be the edge
      * color replicated.
      *
+     * <p>If the bitmap and canvas have different densities, this function
+     * will take care of automatically scaling the bitmap to draw at the
+     * same density as the canvas.
+     * 
      * @param bitmap The bitmap to be drawn
      * @param left   The position of the left side of the bitmap being drawn
      * @param top    The position of the top side of the bitmap being drawn
@@ -959,20 +958,25 @@
     public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
         throwIfRecycled(bitmap);
         native_drawBitmap(mNativeCanvas, bitmap.ni(), left, top,
-                paint != null ? paint.mNativePaint : 0, bitmap.isAutoScalingEnabled(),
-                bitmap.getDensityScale());
+                paint != null ? paint.mNativePaint : 0, mDensity, bitmap.mDensity);
     }
 
     /**
      * Draw the specified bitmap, scaling/translating automatically to fill
      * the destination rectangle. If the source rectangle is not null, it
      * specifies the subset of the bitmap to draw.
-     * Note: if the paint contains a maskfilter that generates a mask which
+     * 
+     * <p>Note: if the paint contains a maskfilter that generates a mask which
      * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
      * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
      * Thus the color outside of the original width/height will be the edge
      * color replicated.
      *
+     * <p>This function <em>ignores the density associated with the bitmap</em>.
+     * This is because the source and destination rectangle coordinate
+     * spaces are in their respective densities, so must already have the
+     * appropriate scaling factor applied.
+     * 
      * @param bitmap The bitmap to be drawn
      * @param src    May be null. The subset of the bitmap to be drawn
      * @param dst    The rectangle that the bitmap will be scaled/translated
@@ -992,12 +996,18 @@
      * Draw the specified bitmap, scaling/translating automatically to fill
      * the destination rectangle. If the source rectangle is not null, it
      * specifies the subset of the bitmap to draw.
-     * Note: if the paint contains a maskfilter that generates a mask which
+     * 
+     * <p>Note: if the paint contains a maskfilter that generates a mask which
      * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
      * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
      * Thus the color outside of the original width/height will be the edge
      * color replicated.
      *
+     * <p>This function <em>ignores the density associated with the bitmap</em>.
+     * This is because the source and destination rectangle coordinate
+     * spaces are in their respective densities, so must already have the
+     * appropriate scaling factor applied.
+     * 
      * @param bitmap The bitmap to be drawn
      * @param src    May be null. The subset of the bitmap to be drawn
      * @param dst    The rectangle that the bitmap will be scaled/translated
@@ -1489,8 +1499,8 @@
                                                int paint);
     private native void native_drawBitmap(int nativeCanvas, int bitmap,
                                                  float left, float top,
-                                                 int nativePaintOrZero, boolean autoScale,
-                                                 float densityScale);
+                                                 int nativePaintOrZero,
+                                                 int canvasDensity, int bitmapDensity);
     private native void native_drawBitmap(int nativeCanvas, int bitmap,
                                                  Rect src, RectF dst,
                                                  int nativePaintOrZero);
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 778c903..88dfd67 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -68,7 +68,7 @@
     }
     
     /** 
-     * Draw a bitmap to nine patches.
+     * Draw a bitmap of nine patches.
      *
      * @param canvas    A container for the current matrix and clip used to draw the bitmap.
      * @param location  Where to draw the bitmap.
@@ -76,23 +76,25 @@
     public void draw(Canvas canvas, RectF location) {
         nativeDraw(canvas.mNativeCanvas, location,
                    mBitmap.ni(), mChunk,
-                   mPaint != null ? mPaint.mNativePaint : 0);
+                   mPaint != null ? mPaint.mNativePaint : 0,
+                   canvas.mDensity, mBitmap.mDensity);
     }
     
     /** 
-     * Draw a bitmap to nine patches.
+     * Draw a bitmap of nine patches.
      *
      * @param canvas    A container for the current matrix and clip used to draw the bitmap.
      * @param location  Where to draw the bitmap.
      */
     public void draw(Canvas canvas, Rect location) {
         nativeDraw(canvas.mNativeCanvas, location,
-                   mBitmap.ni(), mChunk,
-                   mPaint != null ? mPaint.mNativePaint : 0);
+                mBitmap.ni(), mChunk,
+                mPaint != null ? mPaint.mNativePaint : 0,
+                canvas.mDensity, mBitmap.mDensity);
     }
 
     /** 
-     * Draw a bitmap to nine patches.
+     * Draw a bitmap of nine patches.
      *
      * @param canvas    A container for the current matrix and clip used to draw the bitmap.
      * @param location  Where to draw the bitmap.
@@ -100,9 +102,18 @@
      */
     public void draw(Canvas canvas, Rect location, Paint paint) {
         nativeDraw(canvas.mNativeCanvas, location,
-                   mBitmap.ni(), mChunk, paint != null ? paint.mNativePaint : 0);
+                mBitmap.ni(), mChunk, paint != null ? paint.mNativePaint : 0,
+                canvas.mDensity, mBitmap.mDensity);
     }
 
+    /**
+     * Return the underlying bitmap's density, as per
+     * {@link Bitmap#getDensity() Bitmap.getDensity()}.
+     */
+    public int getDensity() {
+        return mBitmap.mDensity;
+    }
+    
     public int getWidth() {
         return mBitmap.getWidth();
     }
@@ -129,9 +140,11 @@
 
     private static native void validateNinePatchChunk(int bitmap, byte[] chunk);
     private static native void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance,
-                                          byte[] c, int paint_instance_or_null);
+                                          byte[] c, int paint_instance_or_null,
+                                          int destDensity, int srcDensity);
     private static native void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance,
-                                          byte[] c, int paint_instance_or_null);
+                                          byte[] c, int paint_instance_or_null,
+                                          int destDensity, int srcDensity);
     private static native int nativeGetTransparentRegion(
             int bitmap, byte[] chunk, Rect location);
 }
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 5b32246..eade73a 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -63,18 +63,56 @@
 
     private boolean mApplyGravity;
     private boolean mRebuildShader;
+    private boolean mMutated;
+    
+    private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
+
+    // These are scaled to match the target density.
     private int mBitmapWidth;
     private int mBitmapHeight;
-    private boolean mMutated;
-
+    
+    /**
+     * Create an empty drawable, not dealing with density.
+     * @deprecated Use {@link #BitmapDrawable(Resources)} to ensure
+     * that the drawable has correctly set its target density.
+     */
     public BitmapDrawable() {
         mBitmapState = new BitmapState((Bitmap) null);
     }
 
+    /**
+     * Create an empty drawable, setting initial target density based on
+     * the display metrics of the resources.
+     */
+    public BitmapDrawable(Resources res) {
+        mBitmapState = new BitmapState((Bitmap) null);
+        if (res != null) {
+            setTargetDensity(res.getDisplayMetrics());
+            mBitmapState.mTargetDensity = mTargetDensity;
+        }
+    }
+
+    /**
+     * Create drawable from a bitmap, not dealing with density.
+     * @deprecated Use {@link #BitmapDrawable(Resources, Bitmap)} to ensure
+     * that the drawable has correctly set its target density.
+     */
     public BitmapDrawable(Bitmap bitmap) {
         this(new BitmapState(bitmap));
     }
 
+    /**
+     * Create drawable from a bitmap, setting initial target density based on
+     * the display metrics of the resources.
+     */
+    public BitmapDrawable(Resources res, Bitmap bitmap) {
+        this(new BitmapState(bitmap));
+        if (res != null) {
+            setTargetDensity(res.getDisplayMetrics());
+            mBitmapState.mTargetDensity = mTargetDensity;
+        }
+    }
+
     public BitmapDrawable(String filepath) {
         this(new BitmapState(BitmapFactory.decodeFile(filepath)));
         if (mBitmap == null) {
@@ -97,11 +135,15 @@
         return mBitmap;
     }
 
+    private void computeBitmapSize() {
+        mBitmapWidth = mBitmap.getScaledWidth(mTargetDensity);
+        mBitmapHeight = mBitmap.getScaledHeight(mTargetDensity);
+    }
+    
     private void setBitmap(Bitmap bitmap) {
         mBitmap = bitmap;
         if (bitmap != null) {
-            mBitmapWidth = bitmap.getWidth();
-            mBitmapHeight = bitmap.getHeight();
+            computeBitmapSize();
         } else {
             mBitmapWidth = mBitmapHeight = -1;
         }
@@ -114,13 +156,11 @@
      *
      * @param canvas The Canvas from which the density scale must be obtained.
      *
-     * @see android.graphics.Bitmap#setDensityScale(float) 
-     * @see android.graphics.Bitmap#getDensityScale()
-     *
-     * @hide pending API council approval
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
      */
-    public void setDensityScale(Canvas canvas) {
-        setDensityScale(canvas.getDensityScale());
+    public void setTargetDensity(Canvas canvas) {
+        setTargetDensity(canvas.getDensity());
     }
 
     /**
@@ -128,32 +168,33 @@
      *
      * @param metrics The DisplayMetrics indicating the density scale for this drawable.
      *
-     * @see android.graphics.Bitmap#setDensityScale(float)
-     * @see android.graphics.Bitmap#getDensityScale()
-     *
-     * @hide pending API council approval
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
      */
-    public void setDensityScale(DisplayMetrics metrics) {
-        setDensityScale(metrics.density);
+    public void setTargetDensity(DisplayMetrics metrics) {
+        mTargetDensity = metrics.densityDpi;
+        if (mBitmap != null) {
+            computeBitmapSize();
+        }
     }
 
     /**
-     * Set the density scale at which this drawable will be rendered.
+     * Set the density at which this drawable will be rendered.
      *
      * @param density The density scale for this drawable.
      *
-     * @see android.graphics.Bitmap#setDensityScale(float)
-     * @see android.graphics.Bitmap#getDensityScale()
-     *
-     * @hide pending API council approval
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
      */
-    public void setDensityScale(float density) {
-        density = (density == Bitmap.DENSITY_SCALE_UNKNOWN ? 1.0f : density);
-        mBitmapState.mTargetDensityScale = density;
+    public void setTargetDensity(int density) {
+        mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
+        if (mBitmap != null) {
+            computeBitmapSize();
+        }
     }
 
     /** Get the gravity used to position/stretch the bitmap within its bounds.
-        See android.view.Gravity
+     * See android.view.Gravity
      * @return the gravity applied to the bitmap
      */
     public int getGravity() {
@@ -302,7 +343,7 @@
         }
         mBitmapState.mBitmap = bitmap;
         setBitmap(bitmap);
-        setDensityScale(r.getDisplayMetrics());
+        setTargetDensity(r.getDisplayMetrics());
 
         final Paint paint = mBitmapState.mPaint;
         paint.setAntiAlias(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_antialias,
@@ -332,29 +373,12 @@
 
     @Override
     public int getIntrinsicWidth() {
-        final Bitmap bitmap = mBitmap;
-        final BitmapState state = mBitmapState;
-
-        if (!state.mAutoScale || state.mBitmapScale == Bitmap.DENSITY_SCALE_UNKNOWN) {
-            return mBitmapWidth;
-        } else {
-            return bitmap != null ? (int) (mBitmapWidth /
-                    (state.mBitmapScale / state.mTargetDensityScale) + 0.5f) : -1;
-
-        }
+        return mBitmapWidth;
     }
 
     @Override
     public int getIntrinsicHeight() {
-        final Bitmap bitmap = mBitmap;
-        final BitmapState state = mBitmapState;
-
-        if (!state.mAutoScale || state.mBitmapScale == Bitmap.DENSITY_SCALE_UNKNOWN) {
-            return mBitmapHeight;
-        } else {
-            return bitmap != null ? (int) (mBitmapHeight /
-                    (state.mBitmapScale / state.mTargetDensityScale) + 0.5f) : -1;
-        }
+        return mBitmapHeight;
     }
 
     @Override
@@ -380,19 +404,10 @@
         Paint mPaint = new Paint(DEFAULT_PAINT_FLAGS);
         Shader.TileMode mTileModeX;
         Shader.TileMode mTileModeY;
-        boolean mAutoScale;
-        float mBitmapScale;
-        float mTargetDensityScale = 1.0f;
+        int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
 
         BitmapState(Bitmap bitmap) {
             mBitmap = bitmap;
-            if (bitmap != null) {
-                mBitmapScale = bitmap.getDensityScale();
-                mAutoScale = bitmap.isAutoScalingEnabled();
-            } else {
-                mBitmapScale = 1.0f;
-                mAutoScale = false;
-            }
         }
 
         BitmapState(BitmapState bitmapState) {
@@ -401,7 +416,7 @@
             mGravity = bitmapState.mGravity;
             mTileModeX = bitmapState.mTileModeX;
             mTileModeY = bitmapState.mTileModeY;
-            mTargetDensityScale = bitmapState.mTargetDensityScale;
+            mTargetDensity = bitmapState.mTargetDensity;
             mPaint = new Paint(bitmapState.mPaint);
         }
 
@@ -418,6 +433,7 @@
 
     private BitmapDrawable(BitmapState state) {
         mBitmapState = state;
+        mTargetDensity = state.mTargetDensity;
         setBitmap(state.mBitmap);
     }
 }
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 4f58a0c..193f399 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -27,6 +27,7 @@
 import android.content.res.TypedArray;
 import android.graphics.*;
 import android.util.AttributeSet;
+import android.util.DisplayMetrics;
 import android.util.StateSet;
 import android.util.Xml;
 import android.util.TypedValue;
@@ -657,9 +658,8 @@
     }
 
     /**
-     * Create a drawable from an inputstream
-     *
-     * @hide pending API council approval
+     * Create a drawable from an inputstream, using the given resources and
+     * value to determine density information.
      */
     public static Drawable createFromResourceStream(Resources res, TypedValue value,
             InputStream is, String srcName) {
@@ -675,7 +675,17 @@
             Rects only to drop them on the floor.
         */
         Rect pad = new Rect();
-        Bitmap  bm = BitmapFactory.decodeStream(res, value, is, pad, null);
+        
+        // Special stuff for compatibility mode: if the target density is not
+        // the same as the display density, but the resource -is- the same as
+        // the display density, then don't scale it down to the target density.
+        // This allows us to load the system's density-correct resources into
+        // an application in compatibility mode, without scaling those down
+        // to the compatibility density only to have them scaled back up when
+        // drawn to the screen.
+        BitmapFactory.Options opts = new BitmapFactory.Options();
+        opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+        Bitmap  bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
         if (bm != null) {
             byte[] np = bm.getNinePatchChunk();
             if (np == null || !NinePatch.isNinePatchChunk(np)) {
@@ -754,10 +764,13 @@
         } else if (name.equals("bitmap")) {
             drawable = new BitmapDrawable();
             if (r != null) {
-               ((BitmapDrawable) drawable).setDensityScale(r.getDisplayMetrics());
+               ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
             }
         } else if (name.equals("nine-patch")) {
             drawable = new NinePatchDrawable();
+            if (r != null) {
+                ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
+             }
         } else {
             throw new XmlPullParserException(parser.getPositionDescription() +
                     ": invalid drawable tag " + name);
@@ -812,15 +825,10 @@
             Rect pad, String srcName) {
 
         if (np != null) {
-            return new NinePatchDrawable(bm, np, pad, srcName);
+            return new NinePatchDrawable(res, bm, np, pad, srcName);
         }
 
-        final BitmapDrawable drawable = new BitmapDrawable(bm);
-        if (res != null) {
-            drawable.setDensityScale(res.getDisplayMetrics());
-        }
-
-        return drawable;
+        return new BitmapDrawable(res, bm);
     }
 }
 
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 376b1df..dc80cf5 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -272,6 +272,8 @@
         boolean     mCheckedConstantState;
         boolean     mCanConstantState;
 
+        boolean     mPaddingChecked = false;
+
         DrawableContainerState(DrawableContainerState orig, DrawableContainer owner) {
             mOwner = owner;
 
@@ -334,6 +336,7 @@
             mHaveStateful = false;
 
             mConstantPadding = null;
+            mPaddingChecked = false;
             mComputedConstantSize = false;
 
             return pos;
@@ -359,23 +362,25 @@
             if (mVariablePadding) {
                 return null;
             }
-            if (mConstantPadding != null) {
+            if (mConstantPadding != null || mPaddingChecked) {
                 return mConstantPadding;
             }
 
-            final Rect r = new Rect(0, 0, 0, 0);
+            Rect r = null;
             final Rect t = new Rect();
             final int N = getChildCount();
             final Drawable[] drawables = mDrawables;
             for (int i = 0; i < N; i++) {
                 if (drawables[i].getPadding(t)) {
+                    if (r == null) r = new Rect(0, 0, 0, 0);
                     if (t.left > r.left) r.left = t.left;
                     if (t.top > r.top) r.top = t.top;
                     if (t.right > r.right) r.right = t.right;
                     if (t.bottom > r.bottom) r.bottom = t.bottom;
                 }
             }
-            return (mConstantPadding=r);
+            mPaddingChecked = true;
+            return (mConstantPadding = r);
         }
 
         public final void setConstantSize(boolean constant) {
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index dace96c..d5c8a08 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -20,6 +20,7 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -41,24 +42,122 @@
     private Paint mPaint;
     private boolean mMutated;
 
+    private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
+
+    // These are scaled to match the target density.
+    private int mBitmapWidth;
+    private int mBitmapHeight;
+    
     NinePatchDrawable() {
     }
 
+    /**
+     * Create drawable from raw nine-patch data, not dealing with density.
+     * @deprecated Use {@link #NinePatchDrawable(Resources, Bitmap, byte[], Rect, String)}
+     * to ensure that the drawable has correctly set its target density.
+     */
     public NinePatchDrawable(Bitmap bitmap, byte[] chunk, Rect padding, String srcName) {
         this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding));
     }
     
+    /**
+     * Create drawable from raw nine-patch data, setting initial target density
+     * based on the display metrics of the resources.
+     */
+    public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk,
+            Rect padding, String srcName) {
+        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding));
+        if (res != null) {
+            setTargetDensity(res.getDisplayMetrics());
+            mNinePatchState.mTargetDensity = mTargetDensity;
+        }
+    }
+    
+    /**
+     * Create drawable from existing nine-patch, not dealing with density.
+     * @deprecated Use {@link #NinePatchDrawable(Resources, NinePatch)}
+     * to ensure that the drawable has correctly set its target density.
+     */
     public NinePatchDrawable(NinePatch patch) {
         this(new NinePatchState(patch, null));
     }
 
+    /**
+     * Create drawable from existing nine-patch, setting initial target density
+     * based on the display metrics of the resources.
+     */
+    public NinePatchDrawable(Resources res, NinePatch patch) {
+        this(new NinePatchState(patch, null));
+        if (res != null) {
+            setTargetDensity(res.getDisplayMetrics());
+            mNinePatchState.mTargetDensity = mTargetDensity;
+        }
+    }
+
     private void setNinePatchState(NinePatchState state) {
         mNinePatchState = state;
         mNinePatch = state.mNinePatch;
         mPadding = state.mPadding;
+        mTargetDensity = state.mTargetDensity;
         if (state.mDither) setDither(state.mDither);
+        if (mNinePatch != null) {
+            computeBitmapSize();
+        }
     }
 
+    /**
+     * Set the density scale at which this drawable will be rendered. This
+     * method assumes the drawable will be rendered at the same density as the
+     * specified canvas.
+     *
+     * @param canvas The Canvas from which the density scale must be obtained.
+     *
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
+     */
+    public void setTargetDensity(Canvas canvas) {
+        setTargetDensity(canvas.getDensity());
+    }
+
+    /**
+     * Set the density scale at which this drawable will be rendered.
+     *
+     * @param metrics The DisplayMetrics indicating the density scale for this drawable.
+     *
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
+     */
+    public void setTargetDensity(DisplayMetrics metrics) {
+        mTargetDensity = metrics.densityDpi;
+        if (mNinePatch != null) {
+            computeBitmapSize();
+        }
+    }
+
+    /**
+     * Set the density at which this drawable will be rendered.
+     *
+     * @param density The density scale for this drawable.
+     *
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
+     */
+    public void setTargetDensity(int density) {
+        mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
+        if (mNinePatch != null) {
+            computeBitmapSize();
+        }
+    }
+
+    private void computeBitmapSize() {
+        final int sdensity = mNinePatch.getDensity();
+        final int tdensity = mTargetDensity;
+        mBitmapWidth = Bitmap.scaleFromDensity(mNinePatch.getWidth(),
+                sdensity, tdensity);
+        mBitmapHeight = Bitmap.scaleFromDensity(mNinePatch.getHeight(),
+                sdensity, tdensity);
+    }
+    
     // overrides
 
     @Override
@@ -111,6 +210,7 @@
         if (dither) {
             options.inDither = false;
         }
+        options.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
 
         final Rect padding = new Rect();        
         Bitmap bitmap = null;
@@ -119,7 +219,7 @@
             final TypedValue value = new TypedValue();
             final InputStream is = r.openRawResource(id, value);
 
-            bitmap = BitmapFactory.decodeStream(r, value, is, padding, options);
+            bitmap = BitmapFactory.decodeResourceStream(r, value, is, padding, options);
 
             is.close();
         } catch (IOException e) {
@@ -136,6 +236,7 @@
 
         setNinePatchState(new NinePatchState(
                 new NinePatch(bitmap, bitmap.getNinePatchChunk(), "XML 9-patch"), padding, dither));
+        mNinePatchState.mTargetDensity = mTargetDensity;
 
         a.recycle();
     }
@@ -153,7 +254,7 @@
      */
     @Override
     public int getIntrinsicWidth() {
-        return mNinePatch.getWidth();
+        return mBitmapWidth;
     }
 
     /**
@@ -161,17 +262,17 @@
      */
     @Override
     public int getIntrinsicHeight() {
-        return mNinePatch.getHeight();
+        return mBitmapHeight;
     }
 
     @Override
     public int getMinimumWidth() {
-        return mNinePatch.getWidth();
+        return mBitmapWidth;
     }
 
     @Override
     public int getMinimumHeight() {
-        return mNinePatch.getHeight();
+        return mBitmapHeight;
     }
 
     /**
@@ -211,6 +312,7 @@
         final Rect mPadding;
         final boolean mDither;
         int mChangingConfigurations;
+        int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
 
         NinePatchState(NinePatch ninePatch, Rect padding) {
             this(ninePatch, padding, false);
@@ -225,8 +327,9 @@
         NinePatchState(NinePatchState state) {
             mNinePatch = new NinePatch(state.mNinePatch);
             mPadding = new Rect(state.mPadding);
-            mChangingConfigurations = state.mChangingConfigurations;
             mDither = state.mDither;
+            mChangingConfigurations = state.mChangingConfigurations;
+            mTargetDensity = state.mTargetDensity;
         }
 
         @Override
diff --git a/libs/rs/java/RenderScript/android/renderscript/Matrix.java b/graphics/java/android/renderscript/Matrix.java
similarity index 99%
rename from libs/rs/java/RenderScript/android/renderscript/Matrix.java
rename to graphics/java/android/renderscript/Matrix.java
index 79b60d0..a266d6b 100644
--- a/libs/rs/java/RenderScript/android/renderscript/Matrix.java
+++ b/graphics/java/android/renderscript/Matrix.java
@@ -20,6 +20,10 @@
 import android.util.Log;
 
 
+/**
+ * @hide
+ *
+ **/
 public class Matrix {
 
     public Matrix() {
diff --git a/libs/rs/java/RenderScript/android/renderscript/ProgramVertexAlloc.java b/graphics/java/android/renderscript/ProgramVertexAlloc.java
similarity index 98%
rename from libs/rs/java/RenderScript/android/renderscript/ProgramVertexAlloc.java
rename to graphics/java/android/renderscript/ProgramVertexAlloc.java
index 020ddb2..82bcc30 100644
--- a/libs/rs/java/RenderScript/android/renderscript/ProgramVertexAlloc.java
+++ b/graphics/java/android/renderscript/ProgramVertexAlloc.java
@@ -20,6 +20,10 @@
 import android.util.Log;
 
 
+/**
+ * @hide
+ *
+ **/
 public class ProgramVertexAlloc {
     public static final int MODELVIEW_OFFSET = 0;
     public static final int PROJECTION_OFFSET = 16;
diff --git a/libs/rs/java/RenderScript/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java
similarity index 99%
rename from libs/rs/java/RenderScript/android/renderscript/RSSurfaceView.java
rename to graphics/java/android/renderscript/RSSurfaceView.java
index 3835793..f024bf6 100644
--- a/libs/rs/java/RenderScript/android/renderscript/RSSurfaceView.java
+++ b/graphics/java/android/renderscript/RSSurfaceView.java
@@ -30,6 +30,10 @@
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 
+/**
+ * @hide
+ *
+ **/
 public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
     private SurfaceHolder mSurfaceHolder;
 
diff --git a/libs/rs/java/RenderScript/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
similarity index 99%
rename from libs/rs/java/RenderScript/android/renderscript/RenderScript.java
rename to graphics/java/android/renderscript/RenderScript.java
index e355635..f829b08 100644
--- a/libs/rs/java/RenderScript/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+/**
+ * @hide
+ *
+ **/
 package android.renderscript;
 
 import java.io.InputStream;
@@ -31,6 +35,10 @@
 import android.graphics.Bitmap;
 import android.graphics.Color;
 
+/**
+ * @hide
+ *
+ **/
 public class RenderScript {
     static final String LOG_TAG = "libRS_jni";
     private static final boolean DEBUG  = false;
@@ -48,7 +56,7 @@
     static {
         sInitialized = false;
         try {
-            System.loadLibrary("RS_jni");
+            System.loadLibrary("rs_jni");
             _nInit();
             sInitialized = true;
         } catch (UnsatisfiedLinkError e) {
diff --git a/libs/rs/jni/Android.mk b/graphics/jni/Android.mk
similarity index 65%
rename from libs/rs/jni/Android.mk
rename to graphics/jni/Android.mk
index f669065..a19134d 100644
--- a/libs/rs/jni/Android.mk
+++ b/graphics/jni/Android.mk
@@ -1,8 +1,10 @@
-LOCAL_PATH:=$(call my-dir)
+ifeq ($(BUILD_RENDERSCRIPT),true)
+
+LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := \
-	RenderScript_jni.cpp
+LOCAL_SRC_FILES:= \
+    android_renderscript_RenderScript.cpp
 
 LOCAL_SHARED_LIBRARIES := \
         libandroid_runtime \
@@ -20,17 +22,18 @@
 
 LOCAL_C_INCLUDES += \
 	$(JNI_H_INCLUDE) \
+	$(LOCAL_PATH)/../../libs/rs \
 	$(rs_generated_include_dir) \
 	$(call include-path-for, corecg graphics)
 
 LOCAL_CFLAGS +=
 
 LOCAL_LDLIBS := -lpthread
-
-LOCAL_MODULE:= libRS_jni
-LOCAL_PRELINK_MODULE := false
-
+LOCAL_ADDITIONAL_DEPENDENCIES := $(addprefix $(rs_generated_include_dir)/,rsgApiFuncDecl.h)
+LOCAL_MODULE:= librs_jni
 LOCAL_ADDITIONAL_DEPENDENCIES += $(rs_generated_source)
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_SHARED_LIBRARY)
 
+endif
diff --git a/libs/rs/jni/RenderScript_jni.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
similarity index 99%
rename from libs/rs/jni/RenderScript_jni.cpp
rename to graphics/jni/android_renderscript_RenderScript.cpp
index 1747673..573610c 100644
--- a/libs/rs/jni/RenderScript_jni.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -32,8 +32,8 @@
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
 
-#include "../RenderScript.h"
-#include "../RenderScriptEnv.h"
+#include <RenderScript.h>
+#include <RenderScriptEnv.h>
 
 //#define LOG_API LOGE
 #define LOG_API(...)
diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
index 6628f75..03ac70a 100644
--- a/include/binder/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -218,8 +218,6 @@
             const sp<HeapInterface>& heap,
             const sp<AllocatorInterface>& allocator);
 
-    virtual ~MemoryDealer();
-
     virtual sp<IMemory> allocate(size_t size, uint32_t flags = 0);
     virtual void        deallocate(size_t offset);
     virtual void        dump(const char* what, uint32_t flags = 0) const;
@@ -228,6 +226,9 @@
     sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
     sp<AllocatorInterface> getAllocator() const { return allocator(); }
 
+protected:
+    virtual ~MemoryDealer();
+
 private:    
     const sp<HeapInterface>&        heap() const;
     const sp<AllocatorInterface>&   allocator() const;
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 83ff508..503cb31 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -39,21 +39,10 @@
 {
 public:
 
-    // input sources values must always be defined in the range
-    // [AudioRecord::DEFAULT_INPUT, AudioRecord::NUM_INPUT_SOURCES[
-    enum input_source {
-        DEFAULT_INPUT   =-1,
-        MIC_INPUT       = 0,
-        VOICE_UPLINK_INPUT = 1,
-        VOICE_DOWNLINK_INPUT = 2,
-        VOICE_CALL_INPUT = 3,
-        NUM_INPUT_SOURCES
-    };
-
     static const int DEFAULT_SAMPLE_RATE = 8000;
 
     /* Events used by AudioRecord callback function (callback_t).
-     * 
+     *
      * to keep in sync with frameworks/base/media/java/android/media/AudioRecord.java
      */
     enum event_type {
@@ -61,7 +50,7 @@
         EVENT_OVERRUN = 1,          // PCM buffer overrun occured.
         EVENT_MARKER = 2,           // Record head is at the specified marker position
                                     // (See setMarkerPosition()).
-        EVENT_NEW_POS = 3,          // Record head is at a new position 
+        EVENT_NEW_POS = 3,          // Record head is at a new position
                                     // (See setPositionUpdatePeriod()).
     };
 
@@ -123,11 +112,11 @@
      *
      * Parameters:
      *
-     * inputSource:        Select the audio input to record to (e.g. AudioRecord::MIC_INPUT).
+     * inputSource:        Select the audio input to record to (e.g. AUDIO_SOURCE_DEFAULT).
      * sampleRate:         Track sampling rate in Hz.
-     * format:             PCM sample format (e.g AudioSystem::PCM_16_BIT for signed
+     * format:             Audio format (e.g AudioSystem::PCM_16_BIT for signed
      *                     16 bits per sample).
-     * channelCount:       Number of PCM channels (e.g 2 for stereo).
+     * channels:           Channel mask: see AudioSystem::audio_channels.
      * frameCount:         Total size of track PCM buffer in frames. This defines the
      *                     latency of the track.
      * flags:              A bitmask of acoustic values from enum record_flags.  It enables
@@ -148,7 +137,7 @@
                         AudioRecord(int inputSource,
                                     uint32_t sampleRate = 0,
                                     int format          = 0,
-                                    int channelCount    = 0,
+                                    uint32_t channels = AudioSystem::CHANNEL_IN_MONO,
                                     int frameCount      = 0,
                                     uint32_t flags      = 0,
                                     callback_t cbf = 0,
@@ -166,14 +155,14 @@
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful intialization
      *  - INVALID_OPERATION: AudioRecord is already intitialized or record device is already in use
-     *  - BAD_VALUE: invalid parameter (channelCount, format, sampleRate...)
+     *  - BAD_VALUE: invalid parameter (channels, format, sampleRate...)
      *  - NO_INIT: audio server or audio hardware not initialized
      *  - PERMISSION_DENIED: recording is not allowed for the requesting process
      * */
             status_t    set(int inputSource     = 0,
                             uint32_t sampleRate = 0,
                             int format          = 0,
-                            int channelCount    = 0,
+                            uint32_t channels = AudioSystem::CHANNEL_IN_MONO,
                             int frameCount      = 0,
                             uint32_t flags      = 0,
                             callback_t cbf = 0,
@@ -199,6 +188,7 @@
 
             int         format() const;
             int         channelCount() const;
+            int         channels() const;
             uint32_t    frameCount() const;
             int         frameSize() const;
             int         inputSource() const;
@@ -222,8 +212,8 @@
 
     /* Sets marker position. When record reaches the number of frames specified,
      * a callback with event type EVENT_MARKER is called. Calling setMarkerPosition
-     * with marker == 0 cancels marker notification callback. 
-     * If the AudioRecord has been opened with no callback function associated, 
+     * with marker == 0 cancels marker notification callback.
+     * If the AudioRecord has been opened with no callback function associated,
      * the operation will fail.
      *
      * Parameters:
@@ -238,10 +228,10 @@
             status_t    getMarkerPosition(uint32_t *marker);
 
 
-    /* Sets position update period. Every time the number of frames specified has been recorded, 
-     * a callback with event type EVENT_NEW_POS is called. 
-     * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification 
-     * callback. 
+    /* Sets position update period. Every time the number of frames specified has been recorded,
+     * a callback with event type EVENT_NEW_POS is called.
+     * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
+     * callback.
      * If the AudioRecord has been opened with no callback function associated,
      * the operation will fail.
      *
@@ -257,8 +247,8 @@
             status_t    getPositionUpdatePeriod(uint32_t *updatePeriod);
 
 
-    /* Gets record head position. The position is the  total number of frames 
-     * recorded since record start. 
+    /* Gets record head position. The position is the  total number of frames
+     * recorded since record start.
      *
      * Parameters:
      *
@@ -270,8 +260,16 @@
      */
             status_t    getPosition(uint32_t *position);
 
-            
-            
+    /* returns a handle on the audio input used by this AudioRecord.
+     *
+     * Parameters:
+     *  none.
+     *
+     * Returned value:
+     *  handle on audio hardware input
+     */
+            audio_io_handle_t    getInput() { return mInput; }
+
     /* obtains a buffer of "frameCount" frames. The buffer must be
      * filled entirely. If the track is stopped, obtainBuffer() returns
      * STOPPED instead of NO_ERROR as long as there are buffers availlable,
@@ -342,6 +340,7 @@
     bool                    mMarkerReached;
     uint32_t                mNewPosition;
     uint32_t                mUpdatePeriod;
+    audio_io_handle_t       mInput;
 };
 
 }; // namespace android
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 3a3a714..0ea04a4 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -24,36 +24,130 @@
 namespace android {
 
 typedef void (*audio_error_callback)(status_t err);
+typedef void * audio_io_handle_t;
+
+class IAudioPolicyService;
+class String8;
 
 class AudioSystem
 {
 public:
 
     enum stream_type {
-        DEFAULT         =-1,
-        VOICE_CALL      = 0,
-        SYSTEM          = 1,
-        RING            = 2,
-        MUSIC           = 3,
-        ALARM           = 4,
-        NOTIFICATION    = 5,
-        BLUETOOTH_SCO   = 6,
+        DEFAULT          =-1,
+        VOICE_CALL       = 0,
+        SYSTEM           = 1,
+        RING             = 2,
+        MUSIC            = 3,
+        ALARM            = 4,
+        NOTIFICATION     = 5,
+        BLUETOOTH_SCO    = 6,
         ENFORCED_AUDIBLE = 7, // Sounds that cannot be muted by user and must be routed to speaker
+        DTMF             = 8,
+        TTS              = 9,
         NUM_STREAM_TYPES
     };
 
-    enum audio_output_type {
-        AUDIO_OUTPUT_DEFAULT      =-1,
-        AUDIO_OUTPUT_HARDWARE     = 0,
-        AUDIO_OUTPUT_A2DP         = 1,
-        NUM_AUDIO_OUTPUT_TYPES
+    // Audio sub formats (see AudioSystem::audio_format).
+    enum pcm_sub_format {
+        PCM_SUB_16_BIT          = 0x1, // must be 1 for backward compatibility
+        PCM_SUB_8_BIT           = 0x2, // must be 2 for backward compatibility
     };
 
+    // MP3 sub format field definition : can use 11 LSBs in the same way as MP3 frame header to specify
+    // bit rate, stereo mode, version...
+    enum mp3_sub_format {
+        //TODO
+    };
+
+    // AMR NB/WB sub format field definition: specify frame block interleaving, bandwidth efficient or octet aligned,
+    // encoding mode for recording...
+    enum amr_sub_format {
+        //TODO
+    };
+
+    // AAC sub format field definition: specify profile or bitrate for recording...
+    enum aac_sub_format {
+        //TODO
+    };
+
+    // VORBIS sub format field definition: specify quality for recording...
+    enum vorbis_sub_format {
+        //TODO
+    };
+
+    // Audio format consists in a main format field (upper 8 bits) and a sub format field (lower 24 bits).
+    // The main format indicates the main codec type. The sub format field indicates options and parameters
+    // for each format. The sub format is mainly used for record to indicate for instance the requested bitrate
+    // or profile. It can also be used for certain formats to give informations not present in the encoded
+    // audio stream (e.g. octet alignement for AMR).
     enum audio_format {
-        FORMAT_DEFAULT = 0,
-        PCM_16_BIT,
-        PCM_8_BIT,
-        INVALID_FORMAT
+        INVALID_FORMAT      = -1,
+        FORMAT_DEFAULT      = 0,
+        PCM                 = 0x00000000, // must be 0 for backward compatibility
+        MP3                 = 0x01000000,
+        AMR_NB              = 0x02000000,
+        AMR_WB              = 0x03000000,
+        AAC                 = 0x04000000,
+        HE_AAC_V1           = 0x05000000,
+        HE_AAC_V2           = 0x06000000,
+        VORBIS              = 0x07000000,
+        MAIN_FORMAT_MASK    = 0xFF000000,
+        SUB_FORMAT_MASK     = 0x00FFFFFF,
+        // Aliases
+        PCM_16_BIT          = (PCM|PCM_SUB_16_BIT),
+        PCM_8_BIT          = (PCM|PCM_SUB_8_BIT)
+    };
+
+
+    // Channel mask definitions must be kept in sync with JAVA values in /media/java/android/media/AudioFormat.java
+    enum audio_channels {
+        // output channels
+        CHANNEL_OUT_FRONT_LEFT = 0x1,
+        CHANNEL_OUT_FRONT_RIGHT = 0x2,
+        CHANNEL_OUT_FRONT_CENTER = 0x4,
+        CHANNEL_OUT_LOW_FREQUENCY = 0x8,
+        CHANNEL_OUT_BACK_LEFT = 0x10,
+        CHANNEL_OUT_BACK_RIGHT = 0x20,
+        CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40,
+        CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80,
+        CHANNEL_OUT_BACK_CENTER = 0x100,
+        CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT,
+        CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT),
+        CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+                CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
+        CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+                CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER),
+        CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+                CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
+        CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+                CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
+                CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
+        CHANNEL_OUT_ALL = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+                CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
+                CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | CHANNEL_OUT_BACK_CENTER),
+
+        // input channels
+        CHANNEL_IN_LEFT = 0x10000,
+        CHANNEL_IN_RIGHT = 0x20000,
+        CHANNEL_IN_FRONT = 0x40000,
+        CHANNEL_IN_BACK = 0x80000,
+        CHANNEL_IN_LEFT_PROCESSED = 0x100000,
+        CHANNEL_IN_RIGHT_PROCESSED = 0x200000,
+        CHANNEL_IN_FRONT_PROCESSED = 0x400000,
+        CHANNEL_IN_BACK_PROCESSED = 0x800000,
+        CHANNEL_IN_PRESSURE = 0x1000000,
+        CHANNEL_IN_X_AXIS = 0x2000000,
+        CHANNEL_IN_Y_AXIS = 0x4000000,
+        CHANNEL_IN_Z_AXIS = 0x8000000,
+        CHANNEL_IN_VOICE_UPLINK = 0x10000000,
+        CHANNEL_IN_VOICE_DNLINK = 0x20000000,
+        CHANNEL_IN_MONO = CHANNEL_IN_FRONT,
+        CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT),
+        CHANNEL_IN_ALL = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT | CHANNEL_IN_FRONT | CHANNEL_IN_BACK|
+                CHANNEL_IN_LEFT_PROCESSED | CHANNEL_IN_RIGHT_PROCESSED | CHANNEL_IN_FRONT_PROCESSED | CHANNEL_IN_BACK_PROCESSED|
+                CHANNEL_IN_PRESSURE | CHANNEL_IN_X_AXIS | CHANNEL_IN_Y_AXIS | CHANNEL_IN_Z_AXIS |
+                CHANNEL_IN_VOICE_UPLINK | CHANNEL_IN_VOICE_DNLINK)
     };
 
     enum audio_mode {
@@ -65,15 +159,6 @@
         NUM_MODES  // not a valid entry, denotes end-of-list
     };
 
-    enum audio_routes {
-        ROUTE_EARPIECE       = (1 << 0),
-        ROUTE_SPEAKER        = (1 << 1),
-        ROUTE_BLUETOOTH_SCO  = (1 << 2),
-        ROUTE_HEADSET        = (1 << 3),
-        ROUTE_BLUETOOTH_A2DP = (1 << 4),
-        ROUTE_ALL            = -1UL,
-    };
-
     enum audio_in_acoustics {
         AGC_ENABLE    = 0x0001,
         AGC_DISABLE   = 0,
@@ -87,36 +172,37 @@
      * only privileged processes can have access to them
      */
 
-    // routing helper functions
-    static status_t speakerphone(bool state);
-    static status_t isSpeakerphoneOn(bool* state);
-    static status_t bluetoothSco(bool state);
-    static status_t isBluetoothScoOn(bool* state);
+    // mute/unmute microphone
     static status_t muteMicrophone(bool state);
     static status_t isMicrophoneMuted(bool *state);
 
+    // set/get master volume
     static status_t setMasterVolume(float value);
-    static status_t setMasterMute(bool mute);
     static status_t getMasterVolume(float* volume);
+    // mute/unmute audio outputs
+    static status_t setMasterMute(bool mute);
     static status_t getMasterMute(bool* mute);
 
-    static status_t setStreamVolume(int stream, float value);
+    // set/get stream volume on specified output
+    static status_t setStreamVolume(int stream, float value, void *output);
+    static status_t getStreamVolume(int stream, float* volume, void *output);
+
+    // mute/unmute stream
     static status_t setStreamMute(int stream, bool mute);
-    static status_t getStreamVolume(int stream, float* volume);
     static status_t getStreamMute(int stream, bool* mute);
 
+    // set audio mode in audio hardware (see AudioSystem::audio_mode)
     static status_t setMode(int mode);
-    static status_t getMode(int* mode);
 
-    static status_t setRouting(int mode, uint32_t routes, uint32_t mask);
-    static status_t getRouting(int mode, uint32_t* routes);
-
+    // returns true if tracks are active on AudioSystem::MUSIC stream
     static status_t isMusicActive(bool *state);
 
-    // Temporary interface, do not use
-    // TODO: Replace with a more generic key:value get/set mechanism
-    static status_t setParameter(const char* key, const char* value);
-    
+    // set/get audio hardware parameters. The function accepts a list of parameters
+    // key value pairs in the form: key1=value1;key2=value2;...
+    // Some keys are reserved for standard parameters (See AudioParameter class).
+    static status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
+    static String8  getParameters(audio_io_handle_t ioHandle, const String8& keys);
+
     static void setErrorCallback(audio_error_callback cb);
 
     // helper function to obtain AudioFlinger service handle
@@ -130,47 +216,247 @@
     static status_t getOutputLatency(uint32_t* latency, int stream = DEFAULT);
 
     static bool routedToA2dpOutput(int streamType);
-    
-    static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount, 
+
+    static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount,
         size_t* buffSize);
 
+
+    //
+    // AudioPolicyService interface
+    //
+
+    enum audio_devices {
+        // output devices
+        DEVICE_OUT_EARPIECE = 0x1,
+        DEVICE_OUT_SPEAKER = 0x2,
+        DEVICE_OUT_WIRED_HEADSET = 0x4,
+        DEVICE_OUT_WIRED_HEADPHONE = 0x8,
+        DEVICE_OUT_BLUETOOTH_SCO = 0x10,
+        DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
+        DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
+        DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
+        DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
+        DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
+        DEVICE_OUT_AUX_DIGITAL = 0x400,
+        DEVICE_OUT_FM_HEADPHONE = 0x800,
+        DEVICE_OUT_FM_SPEAKER = 0x1000,
+        DEVICE_OUT_TTY = 0x2000,
+        DEVICE_OUT_DEFAULT = 0x8000,
+        DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET |
+                DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
+                DEVICE_OUT_BLUETOOTH_SCO_CARKIT | DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+                DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | DEVICE_OUT_FM_HEADPHONE |
+                DEVICE_OUT_FM_SPEAKER | DEVICE_OUT_TTY | DEVICE_OUT_DEFAULT),
+
+        // input devices
+        DEVICE_IN_COMMUNICATION = 0x10000,
+        DEVICE_IN_AMBIENT = 0x20000,
+        DEVICE_IN_BUILTIN_MIC = 0x40000,
+        DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000,
+        DEVICE_IN_WIRED_HEADSET = 0x100000,
+        DEVICE_IN_AUX_DIGITAL = 0x200000,
+        DEVICE_IN_VOICE_CALL = 0x400000,
+        DEVICE_IN_DEFAULT = 0x80000000,
+
+        DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT | DEVICE_IN_BUILTIN_MIC |
+                DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET | DEVICE_IN_AUX_DIGITAL |
+                DEVICE_IN_VOICE_CALL| DEVICE_IN_DEFAULT)
+    };
+
+    // device connection states used for setDeviceConnectionState()
+    enum device_connection_state {
+        DEVICE_STATE_UNAVAILABLE,
+        DEVICE_STATE_AVAILABLE,
+        NUM_DEVICE_STATES
+    };
+
+    // request to open a direct output with getOutput() (by opposition to sharing an output with other AudioTracks)
+    enum output_flags {
+        OUTPUT_FLAG_INDIRECT = 0x0,
+        OUTPUT_FLAG_DIRECT = 0x1
+    };
+
+    // device categories used for setForceUse()
+    enum forced_config {
+        FORCE_NONE,
+        FORCE_SPEAKER,
+        FORCE_HEADPHONES,
+        FORCE_BT_SCO,
+        FORCE_BT_A2DP,
+        FORCE_WIRED_ACCESSORY,
+        NUM_FORCE_CONFIG,
+        FORCE_DEFAULT = FORCE_NONE
+    };
+
+    // usages used for setForceUse()
+    enum force_use {
+        FOR_COMMUNICATION,
+        FOR_MEDIA,
+        FOR_RECORD,
+        NUM_FORCE_USE
+    };
+
+    // types of io configuration change events received with ioConfigChanged()
+    enum io_config_event {
+        OUTPUT_OPENED,
+        OUTPUT_CLOSED,
+        OUTPUT_CONFIG_CHANGED,
+        INPUT_OPENED,
+        INPUT_CLOSED,
+        INPUT_CONFIG_CHANGED,
+        STREAM_CONFIG_CHANGED,
+        NUM_CONFIG_EVENTS
+    };
+
+    // audio output descritor used to cache output configurations in client process to avoid frequent calls
+    // through IAudioFlinger
+    class OutputDescriptor {
+    public:
+        OutputDescriptor()
+        : samplingRate(0), format(0), channels(0), frameCount(0), latency(0)  {}
+
+        uint32_t samplingRate;
+        int32_t format;
+        int32_t channels;
+        size_t frameCount;
+        uint32_t latency;
+    };
+
+    //
+    // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
+    //
+    static status_t setDeviceConnectionState(audio_devices device, device_connection_state state, const char *device_address);
+    static device_connection_state getDeviceConnectionState(audio_devices device, const char *device_address);
+    static status_t setPhoneState(int state);
+    static status_t setRingerMode(uint32_t mode, uint32_t mask);
+    static status_t setForceUse(force_use usage, forced_config config);
+    static forced_config getForceUse(force_use usage);
+    static audio_io_handle_t getOutput(stream_type stream,
+                                        uint32_t samplingRate = 0,
+                                        uint32_t format = FORMAT_DEFAULT,
+                                        uint32_t channels = CHANNEL_OUT_STEREO,
+                                        output_flags flags = OUTPUT_FLAG_INDIRECT);
+    static status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+    static status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+    static void releaseOutput(audio_io_handle_t output);
+    static audio_io_handle_t getInput(int inputSource,
+                                    uint32_t samplingRate = 0,
+                                    uint32_t format = FORMAT_DEFAULT,
+                                    uint32_t channels = CHANNEL_IN_MONO,
+                                    audio_in_acoustics acoustics = (audio_in_acoustics)0);
+    static status_t startInput(audio_io_handle_t input);
+    static status_t stopInput(audio_io_handle_t input);
+    static void releaseInput(audio_io_handle_t input);
+    static status_t initStreamVolume(stream_type stream,
+                                      int indexMin,
+                                      int indexMax);
+    static status_t setStreamVolumeIndex(stream_type stream, int index);
+    static status_t getStreamVolumeIndex(stream_type stream, int *index);
+
+    static const sp<IAudioPolicyService>& get_audio_policy_service();
+
     // ----------------------------------------------------------------------------
 
+    static uint32_t popCount(uint32_t u);
+    static bool isOutputDevice(audio_devices device);
+    static bool isInputDevice(audio_devices device);
+    static bool isA2dpDevice(audio_devices device);
+    static bool isBluetoothScoDevice(audio_devices device);
+    static bool isLowVisibility(stream_type stream);
+    static bool isOutputChannel(uint32_t channel);
+    static bool isInputChannel(uint32_t channel);
+    static bool isValidFormat(uint32_t format);
+    static bool isLinearPCM(uint32_t format);
+
 private:
 
     class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
     {
     public:
-        AudioFlingerClient() {      
+        AudioFlingerClient() {
         }
-        
+
         // DeathRecipient
         virtual void binderDied(const wp<IBinder>& who);
-        
+
         // IAudioFlingerClient
-        virtual void a2dpEnabledChanged(bool enabled);
-        
+
+        // indicate a change in the configuration of an output or input: keeps the cached
+        // values for output/input parameters upto date in client process
+        virtual void ioConfigChanged(int event, void *param1, void *param2);
     };
-    static int getOutput(int streamType);
+
+    class AudioPolicyServiceClient: public IBinder::DeathRecipient
+    {
+    public:
+        AudioPolicyServiceClient() {
+        }
+
+        // DeathRecipient
+        virtual void binderDied(const wp<IBinder>& who);
+    };
 
     static sp<AudioFlingerClient> gAudioFlingerClient;
-
+    static sp<AudioPolicyServiceClient> gAudioPolicyServiceClient;
     friend class AudioFlingerClient;
+    friend class AudioPolicyServiceClient;
 
     static Mutex gLock;
     static sp<IAudioFlinger> gAudioFlinger;
     static audio_error_callback gAudioErrorCallback;
-    static int gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES];
-    static int gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES];
-    static uint32_t gOutLatency[NUM_AUDIO_OUTPUT_TYPES];
-    static bool gA2dpEnabled;
-    
+
     static size_t gInBuffSize;
     // previous parameters for recording buffer size queries
     static uint32_t gPrevInSamplingRate;
     static int gPrevInFormat;
     static int gPrevInChannelCount;
 
+    static sp<IAudioPolicyService> gAudioPolicyService;
+
+    // mapping between stream types and outputs
+    static DefaultKeyedVector<int, audio_io_handle_t> gStreamOutputMap;
+    // list of output descritor containing cached parameters (sampling rate, framecount, channel count...)
+    static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs;
+};
+
+class AudioParameter {
+
+public:
+    AudioParameter() {}
+    AudioParameter(const String8& keyValuePairs);
+    virtual ~AudioParameter();
+
+    // reserved parameter keys for changeing standard parameters with setParameters() function.
+    // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
+    // configuration changes and act accordingly.
+    //  keyRouting: to change audio routing, value is an int in AudioSystem::audio_devices
+    //  keySamplingRate: to change sampling rate routing, value is an int
+    //  keyFormat: to change audio format, value is an int in AudioSystem::audio_format
+    //  keyChannels: to change audio channel configuration, value is an int in AudioSystem::audio_channels
+    //  keyFrameCount: to change audio output frame count, value is an int
+    static const char *keyRouting;
+    static const char *keySamplingRate;
+    static const char *keyFormat;
+    static const char *keyChannels;
+    static const char *keyFrameCount;
+
+    String8 toString();
+
+    status_t add(const String8& key, const String8& value);
+    status_t addInt(const String8& key, const int value);
+    status_t addFloat(const String8& key, const float value);
+
+    status_t remove(const String8& key);
+
+    status_t get(const String8& key, String8& value);
+    status_t getInt(const String8& key, int& value);
+    status_t getFloat(const String8& key, float& value);
+
+    size_t size() { return mParameters.size(); }
+
+private:
+    String8 mKeyValuePairs;
+    KeyedVector <String8, String8> mParameters;
 };
 
 };  // namespace android
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 2e1fbda..981c2f6 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -117,9 +117,9 @@
      * streamType:         Select the type of audio stream this track is attached to
      *                     (e.g. AudioSystem::MUSIC).
      * sampleRate:         Track sampling rate in Hz.
-     * format:             PCM sample format (e.g AudioSystem::PCM_16_BIT for signed
+     * format:             Audio format (e.g AudioSystem::PCM_16_BIT for signed
      *                     16 bits per sample).
-     * channelCount:       Number of PCM channels (e.g 2 for stereo).
+     * channels:           Channel mask: see AudioSystem::audio_channels.
      * frameCount:         Total size of track PCM buffer in frames. This defines the
      *                     latency of the track.
      * flags:              Reserved for future use.
@@ -133,7 +133,7 @@
                         AudioTrack( int streamType,
                                     uint32_t sampleRate  = 0,
                                     int format           = 0,
-                                    int channelCount     = 0,
+                                    int channels         = 0,
                                     int frameCount       = 0,
                                     uint32_t flags       = 0,
                                     callback_t cbf       = 0,
@@ -152,7 +152,7 @@
                         AudioTrack( int streamType,
                                     uint32_t sampleRate = 0,
                                     int format          = 0,
-                                    int channelCount    = 0,
+                                    int channels        = 0,
                                     const sp<IMemory>& sharedBuffer = 0,
                                     uint32_t flags      = 0,
                                     callback_t cbf      = 0,
@@ -169,13 +169,13 @@
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful intialization
      *  - INVALID_OPERATION: AudioTrack is already intitialized
-     *  - BAD_VALUE: invalid parameter (channelCount, format, sampleRate...)
+     *  - BAD_VALUE: invalid parameter (channels, format, sampleRate...)
      *  - NO_INIT: audio server or audio hardware not initialized
      * */
             status_t    set(int streamType      =-1,
                             uint32_t sampleRate = 0,
                             int format          = 0,
-                            int channelCount    = 0,
+                            int channels        = 0,
                             int frameCount      = 0,
                             uint32_t flags      = 0,
                             callback_t cbf      = 0,
@@ -330,6 +330,16 @@
      */
             status_t    reload();
 
+    /* returns a handle on the audio output used by this AudioTrack.
+     *
+     * Parameters:
+     *  none.
+     *
+     * Returned value:
+     *  handle on audio hardware output
+     */
+            audio_io_handle_t    getOutput();
+
     /* obtains a buffer of "frameCount" frames. The buffer must be
      * filled entirely. If the track is stopped, obtainBuffer() returns
      * STOPPED instead of NO_ERROR as long as there are buffers availlable,
@@ -387,7 +397,6 @@
     sp<AudioTrackThread>    mAudioTrackThread;
 
     float                   mVolume[2];
-    uint32_t                mSampleRate;
     uint32_t                mFrameCount;
 
     audio_track_cblk_t*     mCblk;
@@ -395,6 +404,7 @@
     uint8_t                 mFormat;
     uint8_t                 mChannelCount;
     uint8_t                 mMuted;
+    uint32_t                mChannels;
     status_t                mStatus;
     uint32_t                mLatency;
 
@@ -410,6 +420,7 @@
     bool                    mMarkerReached;
     uint32_t                mNewPosition;
     uint32_t                mUpdatePeriod;
+    uint32_t                mFlags;
 };
 
 
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index bac3d29..26e6972f 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -27,7 +27,7 @@
 #include <media/IAudioTrack.h>
 #include <media/IAudioRecord.h>
 #include <media/IAudioFlingerClient.h>
-
+#include <utils/String8.h>
 
 namespace android {
 
@@ -50,11 +50,12 @@
                                 int frameCount,
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
+                                void *output,
                                 status_t *status) = 0;
 
     virtual sp<IAudioRecord> openRecord(
                                 pid_t pid,
-                                int inputSource,
+                                void *input,
                                 uint32_t sampleRate,
                                 int format,
                                 int channelCount,
@@ -65,11 +66,11 @@
     /* query the audio hardware state. This state never changes,
      * and therefore can be cached.
      */
-    virtual     uint32_t    sampleRate(int output) const = 0;
-    virtual     int         channelCount(int output) const = 0;
-    virtual     int         format(int output) const = 0;
-    virtual     size_t      frameCount(int output) const = 0;
-    virtual     uint32_t    latency(int output) const = 0;
+    virtual     uint32_t    sampleRate(void *output) const = 0;
+    virtual     int         channelCount(void *output) const = 0;
+    virtual     int         format(void *output) const = 0;
+    virtual     size_t      frameCount(void *output) const = 0;
+    virtual     uint32_t    latency(void *output) const = 0;
 
     /* set/get the audio hardware state. This will probably be used by
      * the preference panel, mostly.
@@ -83,19 +84,14 @@
     /* set/get stream type state. This will probably be used by
      * the preference panel, mostly.
      */
-    virtual     status_t    setStreamVolume(int stream, float value) = 0;
+    virtual     status_t    setStreamVolume(int stream, float value, void *output) = 0;
     virtual     status_t    setStreamMute(int stream, bool muted) = 0;
 
-    virtual     float       streamVolume(int stream) const = 0;
+    virtual     float       streamVolume(int stream, void *output) const = 0;
     virtual     bool        streamMute(int stream) const = 0;
 
-    // set/get audio routing
-    virtual     status_t    setRouting(int mode, uint32_t routes, uint32_t mask) = 0;
-    virtual     uint32_t    getRouting(int mode) const = 0;
-
-    // set/get audio mode
+    // set audio mode
     virtual     status_t    setMode(int mode) = 0;
-    virtual     int         getMode() const = 0;
 
     // mic mute/state
     virtual     status_t    setMicMute(bool state) = 0;
@@ -104,22 +100,34 @@
     // is a music stream active?
     virtual     bool        isMusicActive() const = 0;
 
-    // pass a generic configuration parameter to libaudio
-    // Temporary interface, do not use
-    // TODO: Replace with a more generic key:value get/set mechanism
-    virtual     status_t  setParameter(const char* key, const char* value) = 0;
+    virtual     status_t    setParameters(void *ioHandle, const String8& keyValuePairs) = 0;
+    virtual     String8     getParameters(void *ioHandle, const String8& keys) = 0;
     
     // register a current process for audio output change notifications
     virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
     
     // retrieve the audio recording buffer size
     virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0;
-    
-    // force AudioFlinger thread out of standby
-    virtual     void        wakeUp() = 0;
 
-    // is A2DP output enabled
-    virtual     bool        isA2dpEnabled() const = 0;
+    virtual void *openOutput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t *pLatencyMs,
+                                    uint32_t flags) = 0;
+    virtual void *openDuplicateOutput(void *output1, void *output2) = 0;
+    virtual status_t closeOutput(void *output) = 0;
+    virtual status_t suspendOutput(void *output) = 0;
+    virtual status_t restoreOutput(void *output) = 0;
+
+    virtual void *openInput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t acoustics) = 0;
+    virtual status_t closeInput(void *input) = 0;
+
+    virtual status_t setStreamOutput(uint32_t stream, void *output) = 0;
 };
 
 
diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h
index 383ec0c..78142ce3 100644
--- a/include/media/IAudioFlingerClient.h
+++ b/include/media/IAudioFlingerClient.h
@@ -20,7 +20,7 @@
 
 #include <utils/RefBase.h>
 #include <binder/IInterface.h>
-
+#include <utils/KeyedVector.h>
 
 namespace android {
 
@@ -31,8 +31,8 @@
 public:
     DECLARE_META_INTERFACE(AudioFlingerClient);
 
-    // Notifies a change of audio output from/to hardware to/from A2DP.
-    virtual void a2dpEnabledChanged(bool enabled) = 0;
+    // Notifies a change of audio input/output configuration.
+    virtual void ioConfigChanged(int event, void *param1, void *param2) = 0;
 
 };
 
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
new file mode 100644
index 0000000..4804bbd
--- /dev/null
+++ b/include/media/IAudioPolicyService.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef ANDROID_IAUDIOPOLICYSERVICE_H
+#define ANDROID_IAUDIOPOLICYSERVICE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <media/AudioSystem.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioPolicyService : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(AudioPolicyService);
+
+    //
+    // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
+    //
+    virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
+                                              AudioSystem::device_connection_state state,
+                                              const char *device_address) = 0;
+    virtual AudioSystem::device_connection_state getDeviceConnectionState(AudioSystem::audio_devices device,
+                                                                          const char *device_address) = 0;
+    virtual status_t setPhoneState(int state) = 0;
+    virtual status_t setRingerMode(uint32_t mode, uint32_t mask) = 0;
+    virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) = 0;
+    virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage) = 0;
+    virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream,
+                                        uint32_t samplingRate = 0,
+                                        uint32_t format = AudioSystem::FORMAT_DEFAULT,
+                                        uint32_t channels = 0,
+                                        AudioSystem::output_flags flags = AudioSystem::OUTPUT_FLAG_INDIRECT) = 0;
+    virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream) = 0;
+    virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream) = 0;
+    virtual void releaseOutput(audio_io_handle_t output) = 0;
+    virtual audio_io_handle_t getInput(int inputSource,
+                                    uint32_t samplingRate = 0,
+                                    uint32_t format = AudioSystem::FORMAT_DEFAULT,
+                                    uint32_t channels = 0,
+                                    AudioSystem::audio_in_acoustics acoustics = (AudioSystem::audio_in_acoustics)0) = 0;
+    virtual status_t startInput(audio_io_handle_t input) = 0;
+    virtual status_t stopInput(audio_io_handle_t input) = 0;
+    virtual void releaseInput(audio_io_handle_t input) = 0;
+    virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+                                      int indexMin,
+                                      int indexMax) = 0;
+    virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index) = 0;
+    virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnAudioPolicyService : public BnInterface<IAudioPolicyService>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOPOLICYSERVICE_H
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 97d55aa..f723cfd 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -26,11 +26,10 @@
 
 #include <media/mediaplayer.h>
 #include <media/AudioSystem.h>
+#include <media/Metadata.h>
 
 namespace android {
 
-typedef int32_t MetadataType;
-
 class Parcel;
 template<typename T> class SortedVector;
 
@@ -129,8 +128,10 @@
     //            the known metadata should be returned.
     // @param[inout] records Parcel where the player appends its metadata.
     // @return OK if the call was successful.
-    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
-                                    Parcel *records) = 0;
+    virtual status_t    getMetadata(const media::Metadata::Filter& ids,
+                                    Parcel *records) {
+        return INVALID_OPERATION;
+    };
 
 protected:
     virtual void        sendEvent(int msg, int ext1=0, int ext2=0) { if (mNotify) mNotify(mCookie, msg, ext1, ext2); }
diff --git a/include/media/Metadata.h b/include/media/Metadata.h
new file mode 100644
index 0000000..241868a
--- /dev/null
+++ b/include/media/Metadata.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef ANDROID_MEDIA_METADATA_H__
+#define ANDROID_MEDIA_METADATA_H__
+
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+
+namespace android {
+class Parcel;
+
+namespace media {
+
+// Metadata is a class to build/serialize a set of metadata in a Parcel.
+//
+// This class should be kept in sync with android/media/Metadata.java.
+// It provides all the metadata ids available and methods to build the
+// header, add records and adjust the set size header field.
+//
+// Typical Usage:
+// ==============
+//  Parcel p;
+//  media::Metadata data(&p);
+//
+//  data.appendHeader();
+//  data.appendBool(Metadata::kPauseAvailable, true);
+//   ... more append ...
+//  data.updateLength();
+//
+
+class Metadata {
+  public:
+    typedef int32_t Type;
+    typedef SortedVector<Type> Filter;
+
+    static const Type kAny = 0;
+
+    // Keep in sync with android/media/Metadata.java
+    static const Type kTitle = 1;           // String
+    static const Type kComment = 2;         // String
+    static const Type kCopyright = 3;       // String
+    static const Type kAlbum = 4;           // String
+    static const Type kArtist = 5;          // String
+    static const Type kAuthor = 6;          // String
+    static const Type kComposer = 7;        // String
+    static const Type kGenre = 8;           // String
+    static const Type kDate = 9;            // Date
+    static const Type kDuration = 10;       // Integer(millisec)
+    static const Type kCdTrackNum = 11;     // Integer 1-based
+    static const Type kCdTrackMax = 12;     // Integer
+    static const Type kRating = 13;         // String
+    static const Type kAlbumArt = 14;       // byte[]
+    static const Type kVideoFrame = 15;     // Bitmap
+    static const Type kCaption = 16;        // TimedText
+
+    static const Type kBitRate = 17;       // Integer, Aggregate rate of
+    // all the streams in bps.
+
+    static const Type kAudioBitRate = 18; // Integer, bps
+    static const Type kVideoBitRate = 19; // Integer, bps
+    static const Type kAudioSampleRate = 20; // Integer, Hz
+    static const Type kVideoframeRate = 21;  // Integer, Hz
+
+    // See RFC2046 and RFC4281.
+    static const Type kMimeType = 22;      // String
+    static const Type kAudioCodec = 23;    // String
+    static const Type kVideoCodec = 24;    // String
+
+    static const Type kVideoHeight = 25;   // Integer
+    static const Type kVideoWidth = 26;    // Integer
+    static const Type kNumTracks = 27;     // Integer
+    static const Type kDrmCrippled = 28;   // Boolean
+
+    // Playback capabilities.
+    static const Type kPauseAvailable = 29;        // Boolean
+    static const Type kSeekBackwardAvailable = 30; // Boolean
+    static const Type kSeekForwardAvailable = 31;  // Boolean
+
+    // @param p[inout] The parcel to append the metadata records
+    // to. The global metadata header should have been set already.
+    explicit Metadata(Parcel *p);
+    ~Metadata();
+
+    // Rewind the underlying parcel, undoing all the changes.
+    void resetParcel();
+
+    // Append the size and 'META' marker.
+    bool appendHeader();
+
+    // Once all the records have been added, call this to update the
+    // lenght field in the header.
+    void updateLength();
+
+    // append* are methods to append metadata.
+    // @param key Is the metadata Id.
+    // @param val Is the value of the metadata.
+    // @return true if successful, false otherwise.
+    // TODO: add more as needed to handle other types.
+    bool appendBool(Type key, bool val);
+    bool appendInt32(Type key, int32_t val);
+
+  private:
+    Metadata(const Metadata&);
+    Metadata& operator=(const Metadata&);
+
+
+    // Checks the key is valid and not already present.
+    bool checkKey(Type key);
+
+    Parcel *mData;
+    size_t mBegin;
+};
+
+}  // namespace android::media
+}  // namespace android
+
+#endif  // ANDROID_MEDIA_METADATA_H__
diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h
index 40ccc14b..8a66152 100644
--- a/include/media/PVPlayer.h
+++ b/include/media/PVPlayer.h
@@ -19,6 +19,7 @@
 
 #include <utils/Errors.h>
 #include <media/MediaPlayerInterface.h>
+#include <media/Metadata.h>
 
 #define MAX_OPENCORE_INSTANCES 25
 
@@ -53,8 +54,9 @@
     virtual status_t    setLooping(int loop);
     virtual player_type playerType() { return PV_PLAYER; }
     virtual status_t    invoke(const Parcel& request, Parcel *reply);
-    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
-                                    Parcel *records);
+    virtual status_t    getMetadata(
+        const SortedVector<media::Metadata::Type>& ids,
+        Parcel *records);
 
     // make available to PlayerDriver
     void        sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); }
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 496a739..8e2db20 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -55,17 +55,18 @@
                     uint32_t    volumeLR;
                 };
                 uint32_t    sampleRate;
+                // NOTE: audio_track_cblk_t::frameSize is not equal to AudioTrack::frameSize() for
+                // 8 bit PCM data: in this case,  mCblk->frameSize is based on a sample size of
+                // 16 bit because data is converted to 16 bit before being stored in buffer
+                uint32_t    frameSize;
                 uint8_t     channels;
                 uint8_t     flowControlFlag; // underrun (out) or overrrun (in) indication
                 uint8_t     out;        // out equals 1 for AudioTrack and 0 for AudioRecord
-                uint8_t     forceReady; 
+                uint8_t     forceReady;
                 uint16_t    bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
                 uint16_t    waitTimeMs;      // Cumulated wait time
-                // Padding ensuring that data buffer starts on a cache line boundary (32 bytes). 
-                // See AudioFlinger::TrackBase constructor
-                int32_t     Padding[1];
-                // Cache line boundary
-                
+                // Cache line boundary (32 bytes)
+
                             audio_track_cblk_t();
                 uint32_t    stepUser(uint32_t frameCount);
                 bool        stepServer(uint32_t frameCount);
diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
index ed084ca..28b0d2f 100644
--- a/include/tts/TtsEngine.h
+++ b/include/tts/TtsEngine.h
@@ -43,7 +43,7 @@
 // @param [inout] void *&       - The userdata pointer set in the original
 //                                 synth call
 // @param [in]    uint32_t      - Track sampling rate in Hz
-// @param [in]    audio_format  - The AudioSystem::audio_format enum
+// @param [in]    uint32_t      - The audio format
 // @param [in]    int           - The number of channels
 // @param [inout] int8_t *&     - A buffer of audio data only valid during the
 //                                execution of the callback
@@ -54,7 +54,7 @@
 //         TTS_CALLBACK_CONTINUE to indicate the synthesis must continue if
 //            there is more data to produce.
 typedef tts_callback_status (synthDoneCB_t)(void *&, uint32_t,
-        AudioSystem::audio_format, int, int8_t *&, size_t&, tts_synth_status);
+        uint32_t, int, int8_t *&, size_t&, tts_synth_status);
 
 class TtsEngine;
 extern "C" TtsEngine* getTtsEngine();
diff --git a/keystore/java/android/security/CertTool.java b/keystore/java/android/security/CertTool.java
index 79418bd..1de007d 100644
--- a/keystore/java/android/security/CertTool.java
+++ b/keystore/java/android/security/CertTool.java
@@ -72,7 +72,7 @@
     private native String getPkcs12PrivateKey(int handle);
     private native String popPkcs12CertificateStack(int handle);
     private native void freePkcs12Handle(int handle);
-    private native String generateCertificateRequest(int bits, String subject);
+    private native String generateCertificateRequest(int bits, String challenge);
     private native boolean isPkcs12Keystore(byte[] data);
     private native int generateX509Certificate(byte[] data);
     private native boolean isCaCertificate(int handle);
@@ -124,7 +124,7 @@
     public String generateKeyPair(int keyStrengthIndex, String challenge,
             String dirName) {
         return generateCertificateRequest(getKeyLength(keyStrengthIndex),
-                dirName);
+                challenge);
     }
 
     private Intent prepareIntent(String title, byte[] data, String namespace,
diff --git a/keystore/java/android/security/Keystore.java b/keystore/java/android/security/Keystore.java
index 1f14da7..a6cfbca 100644
--- a/keystore/java/android/security/Keystore.java
+++ b/keystore/java/android/security/Keystore.java
@@ -48,49 +48,6 @@
     public abstract int remove(String namespace, String keyname);
     public abstract int reset();
 
-    // TODO: for migrating to the mini-keystore, clean up from here
-    /**
-     */
-    public abstract String getCaCertificate(String key);
-
-    /**
-     */
-    public abstract String getUserCertificate(String key);
-
-    /**
-     */
-    public abstract String getUserPrivateKey(String key);
-
-    /**
-     * Returns the array of the certificate keynames in keystore if successful.
-     * Or return an empty array if error.
-     *
-     * @return array of the certificate keynames
-     */
-    public abstract String[] getAllUserCertificateKeys();
-
-    /**
-     */
-    public abstract String[] getAllCaCertificateKeys();
-
-    /**
-     */
-    public abstract String[] getSupportedKeyStrenghs();
-
-    /**
-     * Generates a key pair and returns the certificate request.
-     * @param keyStrengthIndex index to the array of supported key strengths
-     * @param challenge the challenge message in the keygen tag
-     * @param organizations the organization string, e.g.,
-     *      "/C=US/ST={state}/L={city}/O={company}/OU={app}/CN={hostname}"
-     * @return the certificate request
-     */
-    public abstract String generateKeyPair(
-            int keyStrengthIndex, String challenge, String organizations);
-
-    public abstract void addCertificate(byte[] cert);
-    // to here
-
     private static class FileKeystore extends Keystore {
         private static final String SERVICE_NAME = "keystore";
         private static final String CA_CERTIFICATE = "CaCertificate";
@@ -100,69 +57,6 @@
         private static final ServiceCommand mServiceCommand =
                 new ServiceCommand(SERVICE_NAME);
 
-        // TODO: for migrating to the mini-keystore, start from here
-        @Override
-        public String getUserPrivateKey(String key) {
-            return "";
-        }
-
-        @Override
-        public String getUserCertificate(String key) {
-            return "";
-        }
-
-        @Override
-        public String getCaCertificate(String key) {
-            return "";
-        }
-
-        @Override
-        public String[] getAllUserCertificateKeys() {
-            return new String[0];
-        }
-
-        @Override
-        public String[] getAllCaCertificateKeys() {
-          return new String[0];
-        }
-
-        @Override
-        public String[] getSupportedKeyStrenghs() {
-            // TODO: real implementation
-            return new String[] {"High Grade", "Medium Grade"};
-        }
-
-        @Override
-        public String generateKeyPair(int keyStrengthIndex, String challenge,
-                String organizations) {
-            // TODO: real implementation
-            return "-----BEGIN CERTIFICATE REQUEST-----"
-                    + "\nMIICzjCCAbYCAQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh"
-                    + "\nMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRYw"
-                    + "\nFAYDVQQLEw1SZW1vdGUgQWNjZXNzMRAwDgYDVQQLEwdHbGFwdG9wMQ0wCwYDVQQD"
-                    + "\nEwR0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznwy7a16O35u"
-                    + "\nODLQOw6yHAxozrrX1J+c0reiIh8GYohwKrBedFnQ/FnTls6bxY4fNHD+SZvFFgvU"
-                    + "\nECBFOfRmRm7AFo51qT0t2a8qgvDLM6L1qGkmy94W28Q3OlcpF2QianHYdjyGT+Ac"
-                    + "\nYDek1Zi/E/mdPzuVM/K8tkB7n8ktC0PTm1ZtdMRauE5R0WrEhWuF6In/2gy1Q/Zh"
-                    + "\noy7/zQqpbPl2ouulvkx1Y3OXHM6XPNFLoHS1gH0HyAuBUokO0QmetRn6ngJSvz7e"
-                    + "\nVD7QYRppGp+g4BxqaV9XSxhaaKrMs4PAld9enV51X9qjvjCRBve2QxtuJgMfGJdU"
-                    + "\njGr/JweZoQIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBADtxOtEseoLOVYh6sh4b"
-                    + "\nWCdngK87uHn2bdGipFwKdNTxQDdxNQLAKdoGYIfbVsC1cDgFiufeNwVukxxymdnm"
-                    + "\nk0GGK+0O0tZKENv8ysgfbgEsHpJH9FoR5Y5XEq1etejkcgCp59dyhrSk0DLyVm0D"
-                    + "\nIfTC/nsK95H7AAGOkbbDFo2otyLNNrthYncQ9diAG0UzzLacA+86JXZmD3HyC48u"
-                    + "\nI9hsivVnTTfl9afcfVAhfxbQ6HgkhZZjbjFjfABSd4v8wKlAAqK58VxCajNVOVcV"
-                    + "\ncCzOWf6NpE7xEHCf32i8bWDP6hi0WgQcdpQwnZNKhhTLGNb23Uty6HYlJhbxexC7"
-                    + "\nUoM="
-                    + "\n-----END CERTIFICATE REQUEST-----";
-        }
-
-        @Override
-        public void addCertificate(byte[] cert) {
-            // TODO: real implementation
-        }
-
-        // to here
-
         @Override
         public int lock() {
             Reply result = mServiceCommand.execute(ServiceCommand.LOCK, null);
diff --git a/keystore/jni/cert.c b/keystore/jni/cert.c
index 0db28fd..ea21b7d 100644
--- a/keystore/jni/cert.c
+++ b/keystore/jni/cert.c
@@ -36,17 +36,17 @@
     STR(ERR_CONSTRUCT_NEW_DATA),
     STR(ERR_RSA_KEYGEN),
     STR(ERR_X509_PROCESS),
-    STR(ERR_BIO_READ),
+    STR(ERR_SPKAC_TOO_LONG),
+    STR(ERR_INVALID_ARGS),
 };
 
-static void save_in_store(X509_REQ *req, EVP_PKEY *pkey)
+static void save_in_store(EVP_PKEY *pkey)
 {
     EVP_PKEY *newpkey = EVP_PKEY_new();
     RSA *rsa = EVP_PKEY_get1_RSA(pkey);
     EVP_PKEY_set1_RSA(newpkey, rsa);
     PKEY_STORE_free(pkey_store[store_index]);
-    pkey_store[store_index].key_len =
-    i2d_X509_PUBKEY(req->req_info->pubkey, &pkey_store[store_index].public_key);
+    pkey_store[store_index].key_len = i2d_RSAPublicKey(rsa, &pkey_store[store_index].public_key);
     pkey_store[store_index++].pkey = newpkey;
     store_index %= KEYGEN_STORE_SIZE;
     RSA_free(rsa);
@@ -69,17 +69,19 @@
     return (i == KEYGEN_STORE_SIZE) ? NULL : pkey_store[i].pkey;
 }
 
-int gen_csr(int bits, const char *organizations, char reply[REPLY_MAX])
+int gen_csr(int bits, const char *challenge, char reply[REPLY_MAX])
 {
     int len, ret_code = 0;
     BIGNUM *bn = NULL;
-    BIO *bio = NULL;
+    char *spkstr = NULL;
     EVP_PKEY *pkey = NULL;
     RSA *rsa = NULL;
-    X509_REQ *req = NULL;
-    X509_NAME *name = NULL;
+    NETSCAPE_SPKI *req = NULL;
 
-    if ((bio = BIO_new(BIO_s_mem())) == NULL) goto err;
+    if (challenge == NULL) {
+        ret_code = ERR_INVALID_ARGS;
+        goto err;
+    }
 
     if ((bits != KEYLENGTH_MEDIUM) && (bits != KEYLENGTH_MAXIMUM)) {
         ret_code = ERR_INVALID_KEY_LENGTH;
@@ -87,7 +89,7 @@
     }
 
     if (((pkey = EVP_PKEY_new()) == NULL) ||
-        ((req = X509_REQ_new()) == NULL) ||
+        ((req = NETSCAPE_SPKI_new()) == NULL) ||
         ((rsa = RSA_new()) == NULL) || ((bn = BN_new()) == NULL)) {
         ret_code = ERR_CONSTRUCT_NEW_DATA;
         goto err;
@@ -100,40 +102,26 @@
         goto err;
     }
 
-    // rsa will be part of the req, it will be freed in X509_REQ_free(req)
     rsa = NULL;
+    ASN1_STRING_set(req->spkac->challenge, challenge, (int)strlen(challenge));
+    NETSCAPE_SPKI_set_pubkey(req, pkey);
+    NETSCAPE_SPKI_sign(req, pkey, EVP_md5());
+    spkstr = NETSCAPE_SPKI_b64_encode(req);
 
-    X509_REQ_set_pubkey(req, pkey);
-    name = X509_REQ_get_subject_name(req);
-
-    X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
-                               (const unsigned char *)"US", -1, -1, 0);
-    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
-                               (const unsigned char *) ANDROID_KEYSTORE,
-                               -1, -1, 0);
-    X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
-                               (const unsigned char *)organizations, -1, -1, 0);
-
-    if (!X509_REQ_sign(req, pkey, EVP_md5()) ||
-        (PEM_write_bio_X509_REQ(bio, req) <= 0)) {
-        ret_code = ERR_X509_PROCESS;
-        goto err;
-    }
-    if ((len = BIO_read(bio, reply, REPLY_MAX - 1)) > 0) {
-      reply[len] = 0;
-      save_in_store(req, pkey);
+    if ((strlcpy(reply, spkstr, REPLY_MAX)) < REPLY_MAX) {
+        save_in_store(pkey);
     } else {
-      ret_code = ERR_BIO_READ;
+        ret_code = ERR_SPKAC_TOO_LONG;
     }
 
 err:
     if (rsa) RSA_free(rsa);
     if (bn) BN_free(bn);
-    if (req) X509_REQ_free(req);
+    if (req) NETSCAPE_SPKI_free(req);
     if (pkey) EVP_PKEY_free(pkey);
-    if (bio) BIO_free(bio);
+    if (spkstr) OPENSSL_free(spkstr);
     if ((ret_code > 0) && (ret_code < ERR_MAXIMUM)) LOGE(emsg[ret_code]);
-    return ret_code;
+    return -ret_code;
 }
 
 PKCS12 *get_p12_handle(const char *buf, int bufLen)
diff --git a/keystore/jni/cert.h b/keystore/jni/cert.h
index aaa7602..a9e1a9e 100644
--- a/keystore/jni/cert.h
+++ b/keystore/jni/cert.h
@@ -32,8 +32,9 @@
 #define ERR_CONSTRUCT_NEW_DATA  2
 #define ERR_RSA_KEYGEN          3
 #define ERR_X509_PROCESS        4
-#define ERR_BIO_READ            5
-#define ERR_MAXIMUM             6
+#define ERR_SPKAC_TOO_LONG      5
+#define ERR_INVALID_ARGS        6
+#define ERR_MAXIMUM             7
 
 typedef struct {
     EVP_PKEY *pkey;
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index 16a4f2d..6f9e934 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -29,25 +29,41 @@
 
 // ----------------------------------------------------------------------------
 
-A2dpAudioInterface::A2dpAudioInterface() :
-    mOutput(0)
+//AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface()
+//{
+//    AudioHardwareInterface* hw = 0;
+//
+//    hw = AudioHardwareInterface::create();
+//    LOGD("new A2dpAudioInterface(hw: %p)", hw);
+//    hw = new A2dpAudioInterface(hw);
+//    return hw;
+//}
+
+A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
+    mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true)
 {
 }
 
 A2dpAudioInterface::~A2dpAudioInterface()
 {
-    delete mOutput;
+    closeOutputStream((AudioStreamOut *)mOutput);
+    delete mHardwareInterface;
 }
 
 status_t A2dpAudioInterface::initCheck()
 {
-    return 0;
+    if (mHardwareInterface == 0) return NO_INIT;
+    return mHardwareInterface->initCheck();
 }
 
 AudioStreamOut* A2dpAudioInterface::openOutputStream(
-        int format, int channelCount, uint32_t sampleRate, status_t *status)
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
 {
-    LOGD("A2dpAudioInterface::openOutputStream %d, %d, %d\n", format, channelCount, sampleRate);
+    if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) {
+        LOGV("A2dpAudioInterface::openOutputStream() open HW device: %x", devices);
+        return mHardwareInterface->openOutputStream(devices, format, channels, sampleRate, status);
+    }
+
     status_t err = 0;
 
     // only one output stream allowed
@@ -59,71 +75,127 @@
 
     // create new output stream
     A2dpAudioStreamOut* out = new A2dpAudioStreamOut();
-    if ((err = out->set(format, channelCount, sampleRate)) == NO_ERROR) {
+    if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
         mOutput = out;
+        mOutput->setBluetoothEnabled(mBluetoothEnabled);
     } else {
         delete out;
     }
-    
+
     if (status)
         *status = err;
     return mOutput;
 }
 
+void A2dpAudioInterface::closeOutputStream(AudioStreamOut* out) {
+    if (mOutput == 0 || mOutput != out) {
+        LOGW("Attempt to close invalid output stream");
+    }
+    else {
+        delete mOutput;
+        mOutput = 0;
+    }
+}
+
+
 AudioStreamIn* A2dpAudioInterface::openInputStream(
-        int inputSource, int format, int channelCount, uint32_t sampleRate,
-        status_t *status, AudioSystem::audio_in_acoustics acoustics)
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
+        AudioSystem::audio_in_acoustics acoustics)
 {
-    if (status)
-        *status = -1;
-    return NULL;
+    return mHardwareInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
+}
+
+void A2dpAudioInterface::closeInputStream(AudioStreamIn* in)
+{
+    return mHardwareInterface->closeInputStream(in);
+}
+
+status_t A2dpAudioInterface::setMode(int mode)
+{
+    return mHardwareInterface->setMode(mode);
 }
 
 status_t A2dpAudioInterface::setMicMute(bool state)
 {
-    return 0;
+    return mHardwareInterface->setMicMute(state);
 }
 
 status_t A2dpAudioInterface::getMicMute(bool* state)
 {
-    return 0;
+    return mHardwareInterface->getMicMute(state);
 }
 
-status_t A2dpAudioInterface::setParameter(const char *key, const char *value)
+status_t A2dpAudioInterface::setParameters(const String8& keyValuePairs)
 {
-    LOGD("setParameter %s,%s\n", key, value);
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    String8 key;
+    status_t status = NO_ERROR;
 
-    if (!key || !value)
-        return -EINVAL;
+    LOGV("setParameters() %s", keyValuePairs.string());
 
-    if (strcmp(key, "a2dp_sink_address") == 0) {
-        return mOutput->setAddress(value);
-    }
-    if (strcmp(key, "bluetooth_enabled") == 0) {
-        mOutput->setBluetoothEnabled(strcmp(value, "true") == 0);
+    key = "bluetooth_enabled";
+    if (param.get(key, value) == NO_ERROR) {
+        mBluetoothEnabled = (value == "true");
+        if (mOutput) {
+            mOutput->setBluetoothEnabled(mBluetoothEnabled);
+        }
+        param.remove(key);
     }
 
-    return 0;
+    if (param.size()) {
+        status_t hwStatus = mHardwareInterface->setParameters(param.toString());
+        if (status == NO_ERROR) {
+            status = hwStatus;
+        }
+    }
+
+    return status;
+}
+
+String8 A2dpAudioInterface::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    AudioParameter a2dpParam = AudioParameter();
+    String8 value;
+    String8 key;
+
+    key = "bluetooth_enabled";
+    if (param.get(key, value) == NO_ERROR) {
+        value = mBluetoothEnabled ? "true" : "false";
+        a2dpParam.add(key, value);
+        param.remove(key);
+    }
+
+    String8 keyValuePairs  = a2dpParam.toString();
+
+    if (param.size()) {
+        keyValuePairs += ";";
+        keyValuePairs += mHardwareInterface->getParameters(param.toString());
+    }
+
+    LOGV("getParameters() %s", keyValuePairs.string());
+    return keyValuePairs;
+}
+
+size_t A2dpAudioInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+{
+    return mHardwareInterface->getInputBufferSize(sampleRate, format, channelCount);
 }
 
 status_t A2dpAudioInterface::setVoiceVolume(float v)
 {
-    return 0;
+    return mHardwareInterface->setVoiceVolume(v);
 }
 
 status_t A2dpAudioInterface::setMasterVolume(float v)
 {
-    return 0;
-}
-
-status_t A2dpAudioInterface::doRouting()
-{
-    return 0;
+    return mHardwareInterface->setMasterVolume(v);
 }
 
 status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args)
 {
-    return 0;
+    return mHardwareInterface->dumpState(fd, args);
 }
 
 // ----------------------------------------------------------------------------
@@ -132,7 +204,7 @@
     mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
     // assume BT enabled to start, this is safe because its only the
     // enabled->disabled transition we are worried about
-    mBluetoothEnabled(true)
+    mBluetoothEnabled(true), mDevice(0)
 {
     // use any address by default
     strcpy(mA2dpAddress, "00:00:00:00:00:00");
@@ -140,27 +212,43 @@
 }
 
 status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
-        int format, int channels, uint32_t rate)
+        uint32_t device, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
 {
-    LOGD("A2dpAudioStreamOut::set %d, %d, %d\n", format, channels, rate);
+    int lFormat = pFormat ? *pFormat : 0;
+    uint32_t lChannels = pChannels ? *pChannels : 0;
+    uint32_t lRate = pRate ? *pRate : 0;
+
+    LOGD("A2dpAudioStreamOut::set %x, %d, %d, %d\n", device, lFormat, lChannels, lRate);
 
     // fix up defaults
-    if (format == 0) format = AudioSystem::PCM_16_BIT;
-    if (channels == 0) channels = channelCount();
-    if (rate == 0) rate = sampleRate();
+    if (lFormat == 0) lFormat = format();
+    if (lChannels == 0) lChannels = channels();
+    if (lRate == 0) lRate = sampleRate();
 
     // check values
-    if ((format != AudioSystem::PCM_16_BIT) ||
-            (channels != channelCount()) ||
-            (rate != sampleRate()))
+    if ((lFormat != format()) ||
+            (lChannels != channels()) ||
+            (lRate != sampleRate())){
+        if (pFormat) *pFormat = format();
+        if (pChannels) *pChannels = channels();
+        if (pRate) *pRate = sampleRate();
         return BAD_VALUE;
+    }
 
+    if (pFormat) *pFormat = lFormat;
+    if (pChannels) *pChannels = lChannels;
+    if (pRate) *pRate = lRate;
+
+    mDevice = device;
     return NO_ERROR;
 }
 
 A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
 {
+    LOGV("A2dpAudioStreamOut destructor");
+    standby();
     close();
+    LOGV("A2dpAudioStreamOut destructor returning from close()");
 }
 
 ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
@@ -230,6 +318,59 @@
     return result;
 }
 
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    String8 key = String8("a2dp_sink_address");
+    status_t status = NO_ERROR;
+    int device;
+    LOGV("A2dpAudioStreamOut::setParameters() %s", keyValuePairs.string());
+
+    if (param.get(key, value) == NO_ERROR) {
+        if (value.length() != strlen("00:00:00:00:00:00")) {
+            status = BAD_VALUE;
+        } else {
+            setAddress(value.string());
+        }
+        param.remove(key);
+    }
+    key = AudioParameter::keyRouting;
+    if (param.getInt(key, device) == NO_ERROR) {
+        if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device)) {
+            mDevice = device;
+            status = NO_ERROR;
+        } else {
+            status = BAD_VALUE;
+        }
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+String8 A2dpAudioInterface::A2dpAudioStreamOut::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+    String8 key = String8("a2dp_sink_address");
+
+    if (param.get(key, value) == NO_ERROR) {
+        value = mA2dpAddress;
+        param.add(key, value);
+    }
+    key = AudioParameter::keyRouting;
+    if (param.get(key, value) == NO_ERROR) {
+        param.addInt(key, (int)mDevice);
+    }
+
+    LOGV("A2dpAudioStreamOut::getParameters() %s", param.toString().string());
+    return param.toString();
+}
+
 status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
 {
     Mutex::Autolock lock(mLock);
@@ -260,12 +401,14 @@
 status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
 {
     Mutex::Autolock lock(mLock);
+    LOGV("A2dpAudioStreamOut::close() calling close_l()");
     return close_l();
 }
 
 status_t A2dpAudioInterface::A2dpAudioStreamOut::close_l()
 {
     if (mData) {
+        LOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)");
         a2dp_cleanup(mData);
         mData = NULL;
     }
@@ -277,5 +420,4 @@
     return NO_ERROR;
 }
 
-
 }; // namespace android
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index 091e775..d6709e2 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -32,38 +32,44 @@
     class A2dpAudioStreamOut;
 
 public:
-                        A2dpAudioInterface();
+                        A2dpAudioInterface(AudioHardwareInterface* hw);
     virtual             ~A2dpAudioInterface();
     virtual status_t    initCheck();
 
     virtual status_t    setVoiceVolume(float volume);
     virtual status_t    setMasterVolume(float volume);
 
+    virtual status_t    setMode(int mode);
+
     // mic mute
     virtual status_t    setMicMute(bool state);
     virtual status_t    getMicMute(bool* state);
 
-    // Temporary interface, do not use
-    // TODO: Replace with a more generic key:value get/set mechanism
-    virtual status_t    setParameter(const char *key, const char *value);
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+
+    virtual size_t      getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
 
     // create I/O streams
     virtual AudioStreamOut* openOutputStream(
-                                int format=0,
-                                int channelCount=0,
-                                uint32_t sampleRate=0,
+                                uint32_t devices,
+                                int *format=0,
+                                uint32_t *channels=0,
+                                uint32_t *sampleRate=0,
                                 status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
 
     virtual AudioStreamIn* openInputStream(
-                                int inputSource,
-                                int format,
-                                int channelCount,
-                                uint32_t sampleRate,
+                                uint32_t devices,
+                                int *format,
+                                uint32_t *channels,
+                                uint32_t *sampleRate,
                                 status_t *status,
                                 AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
+//    static AudioHardwareInterface* createA2dpInterface();
 
 protected:
-    virtual status_t    doRouting();
     virtual status_t    dump(int fd, const Vector<String16>& args);
 
 private:
@@ -71,19 +77,22 @@
     public:
                             A2dpAudioStreamOut();
         virtual             ~A2dpAudioStreamOut();
-                status_t    set(int format,
-                                int channelCount,
-                                uint32_t sampleRate);
+                status_t    set(uint32_t device,
+                                int *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t *pRate);
         virtual uint32_t    sampleRate() const { return 44100; }
         // SBC codec wants a multiple of 512
         virtual size_t      bufferSize() const { return 512 * 20; }
-        virtual int         channelCount() const { return 2; }
+        virtual uint32_t    channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
         virtual int         format() const { return AudioSystem::PCM_16_BIT; }
         virtual uint32_t    latency() const { return ((1000*bufferSize())/frameSize())/sampleRate() + 200; }
-        virtual status_t    setVolume(float volume) { return INVALID_OPERATION; }
+        virtual status_t    setVolume(float left, float right) { return INVALID_OPERATION; }
         virtual ssize_t     write(const void* buffer, size_t bytes);
                 status_t    standby();
         virtual status_t    dump(int fd, const Vector<String16>& args);
+        virtual status_t    setParameters(const String8& keyValuePairs);
+        virtual String8     getParameters(const String8& keys);
 
     private:
         friend class A2dpAudioInterface;
@@ -102,11 +111,18 @@
                 void*       mData;
                 Mutex       mLock;
                 bool        mBluetoothEnabled;
+                uint32_t    mDevice;
     };
 
+    friend class A2dpAudioStreamOut;
+
     A2dpAudioStreamOut*     mOutput;
+    AudioHardwareInterface  *mHardwareInterface;
+    char        mA2dpAddress[20];
+    bool        mBluetoothEnabled;
 };
 
+
 // ----------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk
index bb224be..c10e02b 100644
--- a/libs/audioflinger/Android.mk
+++ b/libs/audioflinger/Android.mk
@@ -1,13 +1,26 @@
 LOCAL_PATH:= $(call my-dir)
 
+#AUDIO_POLICY_TEST := true
+#ENABLE_AUDIO_DUMP := true
+
 include $(CLEAR_VARS)
 
+
+ifeq ($(AUDIO_POLICY_TEST),true)
+  ENABLE_AUDIO_DUMP := true
+endif
+
+
 LOCAL_SRC_FILES:= \
     AudioHardwareGeneric.cpp \
     AudioHardwareStub.cpp \
-    AudioDumpInterface.cpp \
     AudioHardwareInterface.cpp
 
+ifeq ($(ENABLE_AUDIO_DUMP),true)
+  LOCAL_SRC_FILES += AudioDumpInterface.cpp
+  LOCAL_CFLAGS += -DENABLE_AUDIO_DUMP
+endif
+
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libutils \
@@ -21,8 +34,44 @@
 
 LOCAL_MODULE:= libaudiointerface
 
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+  LOCAL_SRC_FILES += A2dpAudioInterface.cpp
+  LOCAL_SHARED_LIBRARIES += liba2dp
+  LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
+  LOCAL_C_INCLUDES += $(call include-path-for, bluez)
+endif
+
 include $(BUILD_STATIC_LIBRARY)
 
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+    AudioPolicyManagerGeneric.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    libmedia
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_MODULE:= libaudiopolicygeneric
+
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+  LOCAL_CFLAGS += -DWITH_A2DP
+endif
+
+ifeq ($(AUDIO_POLICY_TEST),true)
+  LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=               \
@@ -30,28 +79,38 @@
     AudioMixer.cpp.arm          \
     AudioResampler.cpp.arm      \
     AudioResamplerSinc.cpp.arm  \
-    AudioResamplerCubic.cpp.arm
+    AudioResamplerCubic.cpp.arm \
+    AudioPolicyService.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libutils \
 	libbinder \
     libmedia \
-    libhardware_legacy
+    libhardware_legacy \
+    libaudiopolicygeneric
 
 ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
   LOCAL_STATIC_LIBRARIES += libaudiointerface
+  LOCAL_CFLAGS += -DGENERIC_AUDIO
 else
-  LOCAL_SHARED_LIBRARIES += libaudio
+  LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
+endif
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
 endif
 
 LOCAL_MODULE:= libaudioflinger
 
 ifeq ($(BOARD_HAVE_BLUETOOTH),true)
-  LOCAL_SRC_FILES += A2dpAudioInterface.cpp
-  LOCAL_SHARED_LIBRARIES += liba2dp
   LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
-  LOCAL_C_INCLUDES += $(call include-path-for, bluez)
+endif
+
+ifeq ($(AUDIO_POLICY_TEST),true)
+  LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
 endif
 
 ifeq ($(TARGET_SIMULATOR),true)
diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/libs/audioflinger/AudioDumpInterface.cpp
index b4940cb1..87bb014 100644
--- a/libs/audioflinger/AudioDumpInterface.cpp
+++ b/libs/audioflinger/AudioDumpInterface.cpp
@@ -16,6 +16,7 @@
 */
 
 #define LOG_TAG "AudioFlingerDump"
+//#define LOG_NDEBUG 0
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -28,68 +29,209 @@
 
 namespace android {
 
-bool gFirst = true;       // true if first write after a standby
-
 // ----------------------------------------------------------------------------
 
 AudioDumpInterface::AudioDumpInterface(AudioHardwareInterface* hw)
+    : mFirstHwOutput(true), mPolicyCommands(String8("")), mFileName(String8(""))
 {
     if(hw == 0) {
         LOGE("Dump construct hw = 0");
     }
     mFinalInterface = hw;
-    mStreamOut = 0;
+    LOGV("Constructor %p, mFinalInterface %p", this, mFinalInterface);
 }
 
 
 AudioDumpInterface::~AudioDumpInterface()
 {
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        closeOutputStream((AudioStreamOut *)mOutputs[i]);
+    }
     if(mFinalInterface) delete mFinalInterface;
-    if(mStreamOut) delete mStreamOut;
 }
 
 
 AudioStreamOut* AudioDumpInterface::openOutputStream(
-        int format, int channelCount, uint32_t sampleRate, status_t *status)
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
 {
-    AudioStreamOut* outFinal = mFinalInterface->openOutputStream(format, channelCount, sampleRate, status);
+    AudioStreamOut* outFinal = NULL;
+    int lFormat = AudioSystem::PCM_16_BIT;
+    uint32_t lChannels = AudioSystem::CHANNEL_OUT_STEREO;
+    uint32_t lRate = 44100;
 
-    if(outFinal) {
-        mStreamOut =  new AudioStreamOutDump(outFinal);
-        return mStreamOut;
+
+    if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices) || mFirstHwOutput) {
+        outFinal = mFinalInterface->openOutputStream(devices, format, channels, sampleRate, status);
+        if (outFinal != 0) {
+            lFormat = outFinal->format();
+            lChannels = outFinal->channels();
+            lRate = outFinal->sampleRate();
+            if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) {
+                mFirstHwOutput = false;
+            }
+        }
     } else {
-        LOGE("Dump outFinal=0");
-        return 0;
+        if (format != 0 && *format != 0) lFormat = *format;
+        if (channels != 0 && *channels != 0) lChannels = *channels;
+        if (sampleRate != 0 && *sampleRate != 0) lRate = *sampleRate;
+        if (status) *status = NO_ERROR;
     }
+    LOGV("openOutputStream(), outFinal %p", outFinal);
+
+    AudioStreamOutDump *dumOutput = new AudioStreamOutDump(this, mOutputs.size(), outFinal,
+            devices, lFormat, lChannels, lRate);
+    mOutputs.add(dumOutput);
+
+    return dumOutput;
 }
 
+void AudioDumpInterface::closeOutputStream(AudioStreamOut* out)
+{
+    AudioStreamOutDump *dumpOut = (AudioStreamOutDump *)out;
+
+    if (mOutputs.indexOf(dumpOut) < 0) {
+        LOGW("Attempt to close invalid output stream");
+        return;
+    }
+    dumpOut->standby();
+    if (dumpOut->finalStream() != NULL) {
+        mFinalInterface->closeOutputStream(dumpOut->finalStream());
+    }
+
+    mOutputs.remove(dumpOut);
+    delete dumpOut;
+}
+
+AudioStreamIn* AudioDumpInterface::openInputStream(uint32_t devices, int *format, uint32_t *channels,
+        uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics)
+{
+    AudioStreamIn* inFinal = NULL;
+    int lFormat = AudioSystem::PCM_16_BIT;
+    uint32_t lChannels = AudioSystem::CHANNEL_IN_MONO;
+    uint32_t lRate = 8000;
+
+
+    if (mInputs.size() == 0) {
+        inFinal = mFinalInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
+        if (inFinal == 0) return 0;
+
+        lFormat = inFinal->format();
+        lChannels = inFinal->channels();
+        lRate = inFinal->sampleRate();
+    } else {
+        if (format != 0 && *format != 0) lFormat = *format;
+        if (channels != 0 && *channels != 0) lChannels = *channels;
+        if (sampleRate != 0 && *sampleRate != 0) lRate = *sampleRate;
+        if (status) *status = NO_ERROR;
+    }
+    LOGV("openInputStream(), inFinal %p", inFinal);
+
+    AudioStreamInDump *dumInput = new AudioStreamInDump(this, mInputs.size(), inFinal,
+            devices, lFormat, lChannels, lRate);
+    mInputs.add(dumInput);
+
+    return dumInput;
+}
+void AudioDumpInterface::closeInputStream(AudioStreamIn* in)
+{
+    AudioStreamInDump *dumpIn = (AudioStreamInDump *)in;
+
+    if (mInputs.indexOf(dumpIn) < 0) {
+        LOGW("Attempt to close invalid input stream");
+        return;
+    }
+    dumpIn->standby();
+    if (dumpIn->finalStream() != NULL) {
+        mFinalInterface->closeInputStream(dumpIn->finalStream());
+    }
+
+    mInputs.remove(dumpIn);
+    delete dumpIn;
+}
+
+
+status_t AudioDumpInterface::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    int valueInt;
+    LOGV("setParameters %s", keyValuePairs.string());
+
+    if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
+        mFileName = value;
+        return NO_ERROR;
+    }
+    if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
+        Mutex::Autolock _l(mLock);
+        param.remove(String8("test_cmd_policy"));
+        mPolicyCommands = param.toString();
+        LOGV("test_cmd_policy command %s written", mPolicyCommands.string());
+        return NO_ERROR;
+    }
+
+    if (mFinalInterface != 0 ) return mFinalInterface->setParameters(keyValuePairs);
+    return NO_ERROR;
+}
+
+String8 AudioDumpInterface::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+
+//    LOGV("getParameters %s", keys.string());
+
+    if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
+        return mFileName;
+    }
+    if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
+        Mutex::Autolock _l(mLock);
+//        LOGV("test_cmd_policy command %s read", mPolicyCommands.string());
+        return mPolicyCommands;
+    }
+
+    if (mFinalInterface != 0 ) return mFinalInterface->getParameters(keys);
+    return String8("");
+}
+
+
 // ----------------------------------------------------------------------------
 
-AudioStreamOutDump::AudioStreamOutDump( AudioStreamOut* finalStream)
+AudioStreamOutDump::AudioStreamOutDump(AudioDumpInterface *interface,
+                                        int id,
+                                        AudioStreamOut* finalStream,
+                                        uint32_t devices,
+                                        int format,
+                                        uint32_t channels,
+                                        uint32_t sampleRate)
+    : mInterface(interface), mId(id),
+      mSampleRate(sampleRate), mFormat(format), mChannels(channels), mLatency(0), mDevice(devices),
+      mBufferSize(1024), mFinalStream(finalStream), mOutFile(0), mFileCount(0)
 {
-    mFinalStream = finalStream;
-    mOutFile = 0;
+    LOGV("AudioStreamOutDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
 }
 
 
 AudioStreamOutDump::~AudioStreamOutDump()
 {
     Close();
-    delete mFinalStream;
 }
 
 ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes)
 {
     ssize_t ret;
 
-    ret = mFinalStream->write(buffer, bytes);
-    if(!mOutFile && gFirst) {
-        gFirst = false;
-        // check if dump file exist
-        mOutFile = fopen(FLINGER_DUMP_NAME, "r");
-        if(mOutFile) {
-            fclose(mOutFile);
-            mOutFile = fopen(FLINGER_DUMP_NAME, "ab");
+    if (mFinalStream) {
+        ret = mFinalStream->write(buffer, bytes);
+    } else {
+        usleep((bytes * 1000000) / frameSize() / sampleRate());
+        ret = bytes;
+    }
+    if(!mOutFile) {
+        if (mInterface->fileName() != "") {
+            char name[255];
+            sprintf(name, "%s_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount);
+            mOutFile = fopen(name, "wb");
+            LOGV("Opening dump file %s, fh %p", name, mOutFile);
         }
     }
     if (mOutFile) {
@@ -100,13 +242,65 @@
 
 status_t AudioStreamOutDump::standby()
 {
+    LOGV("AudioStreamOutDump standby(), mOutFile %p, mFinalStream %p", mOutFile, mFinalStream);
+
     Close();
-    gFirst = true;
-    return mFinalStream->standby();
+    if (mFinalStream != 0 ) return mFinalStream->standby();
+    return NO_ERROR;
 }
 
+uint32_t AudioStreamOutDump::sampleRate() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->sampleRate();
+    return mSampleRate;
+}
 
-void AudioStreamOutDump::Close(void)
+size_t AudioStreamOutDump::bufferSize() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->bufferSize();
+    return mBufferSize;
+}
+
+uint32_t AudioStreamOutDump::channels() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->channels();
+    return mChannels;
+}
+int AudioStreamOutDump::format() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->format();
+    return mFormat;
+}
+uint32_t AudioStreamOutDump::latency() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->latency();
+    return 0;
+}
+status_t AudioStreamOutDump::setVolume(float left, float right)
+{
+    if (mFinalStream != 0 ) return mFinalStream->setVolume(left, right);
+    return NO_ERROR;
+}
+status_t AudioStreamOutDump::setParameters(const String8& keyValuePairs)
+{
+    LOGV("AudioStreamOutDump::setParameters()");
+    if (mFinalStream != 0 ) return mFinalStream->setParameters(keyValuePairs);
+    return NO_ERROR;
+}
+String8 AudioStreamOutDump::getParameters(const String8& keys)
+{
+    String8 result = String8("");
+    if (mFinalStream != 0 ) result = mFinalStream->getParameters(keys);
+    return result;
+}
+
+status_t AudioStreamOutDump::dump(int fd, const Vector<String16>& args)
+{
+    if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
+    return NO_ERROR;
+}
+
+void AudioStreamOutDump::Close()
 {
     if(mOutFile) {
         fclose(mOutFile);
@@ -114,4 +308,140 @@
     }
 }
 
+// ----------------------------------------------------------------------------
+
+AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface,
+                                        int id,
+                                        AudioStreamIn* finalStream,
+                                        uint32_t devices,
+                                        int format,
+                                        uint32_t channels,
+                                        uint32_t sampleRate)
+    : mInterface(interface), mId(id),
+      mSampleRate(sampleRate), mFormat(format), mChannels(channels), mDevice(devices),
+      mBufferSize(1024), mFinalStream(finalStream), mInFile(0)
+{
+    LOGV("AudioStreamInDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
+}
+
+
+AudioStreamInDump::~AudioStreamInDump()
+{
+    Close();
+}
+
+ssize_t AudioStreamInDump::read(void* buffer, ssize_t bytes)
+{
+    if (mFinalStream) {
+        return mFinalStream->read(buffer, bytes);
+    }
+
+    usleep((bytes * 1000000) / frameSize() / sampleRate());
+
+    if(!mInFile) {
+        char name[255];
+        strcpy(name, "/sdcard/music/sine440");
+        if (channels() == AudioSystem::CHANNEL_IN_MONO) {
+            strcat(name, "_mo");
+        } else {
+            strcat(name, "_st");
+        }
+        if (format() == AudioSystem::PCM_16_BIT) {
+            strcat(name, "_16b");
+        } else {
+            strcat(name, "_8b");
+        }
+        if (sampleRate() < 16000) {
+            strcat(name, "_8k");
+        } else if (sampleRate() < 32000) {
+            strcat(name, "_22k");
+        } else if (sampleRate() < 48000) {
+            strcat(name, "_44k");
+        } else {
+            strcat(name, "_48k");
+        }
+        strcat(name, ".wav");
+        mInFile = fopen(name, "rb");
+        LOGV("Opening dump file %s, fh %p", name, mInFile);
+        if (mInFile) {
+            fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
+        }
+
+    }
+    if (mInFile) {
+        ssize_t bytesRead = fread(buffer, bytes, 1, mInFile);
+        if (bytesRead != bytes) {
+            fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
+            fread((uint8_t *)buffer+bytesRead, bytes-bytesRead, 1, mInFile);
+        }
+    }
+    return bytes;
+}
+
+status_t AudioStreamInDump::standby()
+{
+    LOGV("AudioStreamInDump standby(), mInFile %p, mFinalStream %p", mInFile, mFinalStream);
+
+    Close();
+    if (mFinalStream != 0 ) return mFinalStream->standby();
+    return NO_ERROR;
+}
+
+status_t AudioStreamInDump::setGain(float gain)
+{
+    if (mFinalStream != 0 ) return mFinalStream->setGain(gain);
+    return NO_ERROR;
+}
+
+uint32_t AudioStreamInDump::sampleRate() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->sampleRate();
+    return mSampleRate;
+}
+
+size_t AudioStreamInDump::bufferSize() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->bufferSize();
+    return mBufferSize;
+}
+
+uint32_t AudioStreamInDump::channels() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->channels();
+    return mChannels;
+}
+
+int AudioStreamInDump::format() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->format();
+    return mFormat;
+}
+
+status_t AudioStreamInDump::setParameters(const String8& keyValuePairs)
+{
+    LOGV("AudioStreamInDump::setParameters()");
+    if (mFinalStream != 0 ) return mFinalStream->setParameters(keyValuePairs);
+    return NO_ERROR;
+}
+
+String8 AudioStreamInDump::getParameters(const String8& keys)
+{
+    String8 result = String8("");
+    if (mFinalStream != 0 ) result = mFinalStream->getParameters(keys);
+    return result;
+}
+
+status_t AudioStreamInDump::dump(int fd, const Vector<String16>& args)
+{
+    if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
+    return NO_ERROR;
+}
+
+void AudioStreamInDump::Close()
+{
+    if(mInFile) {
+        fclose(mInFile);
+        mInFile = 0;
+    }
+}
 }; // namespace android
diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h
index b72c94e..4de4a16 100644
--- a/libs/audioflinger/AudioDumpInterface.h
+++ b/libs/audioflinger/AudioDumpInterface.h
@@ -20,35 +20,94 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <utils/String8.h>
+#include <utils/SortedVector.h>
 
 #include <hardware_legacy/AudioHardwareBase.h>
 
 namespace android {
 
-#define FLINGER_DUMP_NAME "/data/FlingerOut.pcm" // name of file used for dump
+#define AUDIO_DUMP_WAVE_HDR_SIZE 44
+
+class AudioDumpInterface;
 
 class AudioStreamOutDump : public AudioStreamOut {
 public:
-                        AudioStreamOutDump( AudioStreamOut* FinalStream);
+                        AudioStreamOutDump(AudioDumpInterface *interface,
+                                            int id,
+                                            AudioStreamOut* finalStream,
+                                            uint32_t devices,
+                                            int format,
+                                            uint32_t channels,
+                                            uint32_t sampleRate);
                         ~AudioStreamOutDump();
-                        virtual ssize_t     write(const void* buffer, size_t bytes);
 
-    virtual uint32_t    sampleRate() const { return mFinalStream->sampleRate(); }
-    virtual size_t      bufferSize() const { return mFinalStream->bufferSize(); }
-    virtual int         channelCount() const { return mFinalStream->channelCount(); }
-    virtual int         format() const { return mFinalStream->format(); }
-    virtual uint32_t    latency() const { return mFinalStream->latency(); }
-    virtual status_t    setVolume(float volume)
-                            { return mFinalStream->setVolume(volume); }
+    virtual ssize_t     write(const void* buffer, size_t bytes);
+    virtual uint32_t    sampleRate() const;
+    virtual size_t      bufferSize() const;
+    virtual uint32_t    channels() const;
+    virtual int         format() const;
+    virtual uint32_t    latency() const;
+    virtual status_t    setVolume(float left, float right);
     virtual status_t    standby();
-    virtual status_t    dump(int fd, const Vector<String16>& args) { return mFinalStream->dump(fd, args); }
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+    virtual status_t    dump(int fd, const Vector<String16>& args);
     void                Close(void);
+    AudioStreamOut*     finalStream() { return mFinalStream; }
+    uint32_t            device() { return mDevice; }
 
 private:
+    AudioDumpInterface *mInterface;
+    int                  mId;
+    uint32_t mSampleRate;               //
+    uint32_t mFormat;                   //
+    uint32_t mChannels;                 // output configuration
+    uint32_t mLatency;                  //
+    uint32_t mDevice;                   // current device this output is routed to
+    size_t  mBufferSize;
     AudioStreamOut      *mFinalStream;
-    FILE                *mOutFile;     // output file
+    FILE                *mOutFile;      // output file
+    int                 mFileCount;
 };
 
+class AudioStreamInDump : public AudioStreamIn {
+public:
+                        AudioStreamInDump(AudioDumpInterface *interface,
+                                            int id,
+                                            AudioStreamIn* finalStream,
+                                            uint32_t devices,
+                                            int format,
+                                            uint32_t channels,
+                                            uint32_t sampleRate);
+                        ~AudioStreamInDump();
+
+    virtual uint32_t    sampleRate() const;
+    virtual size_t      bufferSize() const;
+    virtual uint32_t    channels() const;
+    virtual int         format() const;
+
+    virtual status_t    setGain(float gain);
+    virtual ssize_t     read(void* buffer, ssize_t bytes);
+    virtual status_t    standby();
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+    void                Close(void);
+    AudioStreamIn*     finalStream() { return mFinalStream; }
+    uint32_t            device() { return mDevice; }
+
+private:
+    AudioDumpInterface *mInterface;
+    int                  mId;
+    uint32_t mSampleRate;               //
+    uint32_t mFormat;                   //
+    uint32_t mChannels;                 // output configuration
+    uint32_t mDevice;                   // current device this output is routed to
+    size_t  mBufferSize;
+    AudioStreamIn      *mFinalStream;
+    FILE                *mInFile;      // output file
+};
 
 class AudioDumpInterface : public AudioHardwareBase
 {
@@ -56,10 +115,13 @@
 public:
                         AudioDumpInterface(AudioHardwareInterface* hw);
     virtual AudioStreamOut* openOutputStream(
-                                int format=0,
-                                int channelCount=0,
-                                uint32_t sampleRate=0,
+                                uint32_t devices,
+                                int *format=0,
+                                uint32_t *channels=0,
+                                uint32_t *sampleRate=0,
                                 status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
+
     virtual             ~AudioDumpInterface();
 
     virtual status_t    initCheck()
@@ -75,21 +137,25 @@
     virtual status_t    getMicMute(bool* state)
                             {return mFinalInterface->getMicMute(state);}
 
-    virtual status_t    setParameter(const char* key, const char* value)
-                            {return mFinalInterface->setParameter(key, value);}
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
 
-    virtual AudioStreamIn* openInputStream(int inputSource, int format, int channelCount,
-            uint32_t sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics)
-        { return mFinalInterface->openInputStream(inputSource, format, channelCount, sampleRate, status, acoustics); }
+    virtual AudioStreamIn* openInputStream(uint32_t devices, int *format, uint32_t *channels,
+            uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
 
     virtual status_t    dump(int fd, const Vector<String16>& args) { return mFinalInterface->dumpState(fd, args); }
 
+            String8     fileName() const { return mFileName; }
 protected:
-    virtual status_t    doRouting() {return mFinalInterface->setRouting(mMode, mRoutes[mMode]);}
 
-    AudioHardwareInterface  *mFinalInterface;
-    AudioStreamOutDump      *mStreamOut;
-
+    AudioHardwareInterface          *mFinalInterface;
+    SortedVector<AudioStreamOutDump *>    mOutputs;
+    bool                            mFirstHwOutput;
+    SortedVector<AudioStreamInDump *>    mInputs;
+    Mutex                           mLock;
+    String8                         mPolicyCommands;
+    String8                         mFileName;
 };
 
 }; // namespace android
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index ffc0278..1336131 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -71,15 +71,9 @@
 static const int8_t kMaxTrackRetries = 50;
 static const int8_t kMaxTrackStartupRetries = 50;
 
-static const int kStartSleepTime = 30000;
-static const int kStopSleepTime = 30000;
-
 static const int kDumpLockRetries = 50;
 static const int kDumpLockSleep = 20000;
 
-// Maximum number of pending buffers allocated by OutputTrack::write()
-static const uint8_t kMaxOutputTrackBuffers = 5;
-
 
 #define AUDIOFLINGER_SECURITY_ENABLED 1
 
@@ -121,132 +115,32 @@
 
 AudioFlinger::AudioFlinger()
     : BnAudioFlinger(),
-        mAudioHardware(0), mA2dpAudioInterface(0), mA2dpEnabled(false), mNotifyA2dpChange(false),
-        mForcedSpeakerCount(0), mA2dpDisableCount(0), mA2dpSuppressed(false), mForcedRoute(0),
-        mRouteRestoreTime(0), mMusicMuteSaved(false)
+        mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false)
 {
     mHardwareStatus = AUDIO_HW_IDLE;
+
     mAudioHardware = AudioHardwareInterface::create();
+
     mHardwareStatus = AUDIO_HW_INIT;
     if (mAudioHardware->initCheck() == NO_ERROR) {
         // open 16-bit output stream for s/w mixer
-        mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
-        status_t status;
-        AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
-        mHardwareStatus = AUDIO_HW_IDLE;
-        if (hwOutput) {
-            mHardwareMixerThread = new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE);
-        } else {
-            LOGE("Failed to initialize hardware output stream, status: %d", status);
-        }
-        
-#ifdef WITH_A2DP
-        // Create A2DP interface
-        mA2dpAudioInterface = new A2dpAudioInterface();
-        AudioStreamOut *a2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
-        if (a2dpOutput) {
-            mA2dpMixerThread = new MixerThread(this, a2dpOutput, AudioSystem::AUDIO_OUTPUT_A2DP);
-            if (hwOutput) {  
-                uint32_t frameCount = ((a2dpOutput->bufferSize()/a2dpOutput->frameSize()) * hwOutput->sampleRate()) / a2dpOutput->sampleRate();
-                MixerThread::OutputTrack *a2dpOutTrack = new MixerThread::OutputTrack(mA2dpMixerThread,
-                                                            hwOutput->sampleRate(),
-                                                            AudioSystem::PCM_16_BIT,
-                                                            hwOutput->channelCount(),
-                                                            frameCount);
-                mHardwareMixerThread->setOuputTrack(a2dpOutTrack);                
-            }
-        } else {
-            LOGE("Failed to initialize A2DP output stream, status: %d", status);
-        }
-#endif
- 
-        // FIXME - this should come from settings
-        setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
-        setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
-        setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL);
+
         setMode(AudioSystem::MODE_NORMAL);
 
         setMasterVolume(1.0f);
         setMasterMute(false);
-
-        // Start record thread
-        mAudioRecordThread = new AudioRecordThread(mAudioHardware, this);
-        if (mAudioRecordThread != 0) {
-            mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO);            
-        }
-     } else {
+    } else {
         LOGE("Couldn't even initialize the stubbed audio hardware!");
     }
 }
 
 AudioFlinger::~AudioFlinger()
 {
-    if (mAudioRecordThread != 0) {
-        mAudioRecordThread->exit();
-        mAudioRecordThread.clear();        
-    }
-    mHardwareMixerThread.clear();
-    delete mAudioHardware;
-    // deleting mA2dpAudioInterface also deletes mA2dpOutput;
-#ifdef WITH_A2DP
-    mA2dpMixerThread.clear();
-    delete mA2dpAudioInterface;
-#endif
+    mRecordThreads.clear();
+    mPlaybackThreads.clear();
 }
 
 
-#ifdef WITH_A2DP
-// setA2dpEnabled_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::setA2dpEnabled_l(bool enable)
-{    
-    SortedVector < sp<MixerThread::Track> > tracks;
-    SortedVector < wp<MixerThread::Track> > activeTracks;
-    
-    LOGV_IF(enable, "set output to A2DP\n");
-    LOGV_IF(!enable, "set output to hardware audio\n");
-
-    // Transfer tracks playing on MUSIC stream from one mixer to the other
-    if (enable) {
-        mHardwareMixerThread->getTracks_l(tracks, activeTracks);
-        mA2dpMixerThread->putTracks_l(tracks, activeTracks);
-    } else {
-        mA2dpMixerThread->getTracks_l(tracks, activeTracks);
-        mHardwareMixerThread->putTracks_l(tracks, activeTracks);
-        mA2dpMixerThread->mOutput->standby();
-    }
-    mA2dpEnabled = enable;
-    mNotifyA2dpChange = true;
-    mWaitWorkCV.broadcast();
-}
-
-// checkA2dpEnabledChange_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::checkA2dpEnabledChange_l()
-{
-    if (mNotifyA2dpChange) {
-        // Notify AudioSystem of the A2DP activation/deactivation
-        size_t size = mNotificationClients.size();
-        for (size_t i = 0; i < size; i++) {
-            sp<IBinder> binder = mNotificationClients.itemAt(i).promote();
-            if (binder != NULL) {
-                LOGV("Notifying output change to client %p", binder.get());
-                sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
-                client->a2dpEnabledChanged(mA2dpEnabled);
-            }
-        }
-        mNotifyA2dpChange = false;
-    }
-}
-#endif // WITH_A2DP
-
-bool AudioFlinger::streamForcedToSpeaker(int streamType)
-{
-    // NOTE that streams listed here must not be routed to A2DP by default:
-    // AudioSystem::routedToA2dpOutput(streamType) == false
-    return (streamType == AudioSystem::RING ||
-            streamType == AudioSystem::ALARM ||
-            streamType == AudioSystem::NOTIFICATION ||
-            streamType == AudioSystem::ENFORCED_AUDIBLE);
-}
 
 status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
 {
@@ -276,10 +170,7 @@
     char buffer[SIZE];
     String8 result;
     int hardwareStatus = mHardwareStatus;
-    
-    if (hardwareStatus == AUDIO_HW_IDLE && mHardwareMixerThread->mStandby) {
-        hardwareStatus = AUDIO_HW_STANDBY;
-    }
+
     snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
     result.append(buffer);
     write(fd, result.string(), result.size());
@@ -337,13 +228,16 @@
 
         dumpClients(fd, args);
         dumpInternals(fd, args);
-        mHardwareMixerThread->dump(fd, args);
-#ifdef WITH_A2DP
-        mA2dpMixerThread->dump(fd, args);
-#endif
 
-        // dump record client
-        if (mAudioRecordThread != 0) mAudioRecordThread->dump(fd, args);
+        // dump playback threads
+        for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+            mPlaybackThreads[i]->dump(fd, args);
+        }
+
+        // dump record threads
+        for (size_t i = 0; i < mRecordThreads.size(); i++) {
+            mRecordThreads[i]->dump(fd, args);
+        }
 
         if (mAudioHardware) {
             mAudioHardware->dumpState(fd, args);
@@ -353,6 +247,7 @@
     return NO_ERROR;
 }
 
+
 // IAudioFlinger interface
 
 
@@ -365,9 +260,10 @@
         int frameCount,
         uint32_t flags,
         const sp<IMemory>& sharedBuffer,
+        void *output,
         status_t *status)
 {
-    sp<MixerThread::Track> track;
+    sp<PlaybackThread::Track> track;
     sp<TrackHandle> trackHandle;
     sp<Client> client;
     wp<Client> wclient;
@@ -381,6 +277,12 @@
 
     {
         Mutex::Autolock _l(mLock);
+        PlaybackThread *thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            LOGE("unknown output thread");
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
 
         wclient = mClients.valueFor(pid);
 
@@ -390,16 +292,8 @@
             client = new Client(this, pid);
             mClients.add(pid, client);
         }
-#ifdef WITH_A2DP
-        if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) {
-            track = mA2dpMixerThread->createTrack_l(client, streamType, sampleRate, format,
-                    channelCount, frameCount, sharedBuffer, &lStatus);            
-        } else 
-#endif
-        {
-            track = mHardwareMixerThread->createTrack_l(client, streamType, sampleRate, format,
-                    channelCount, frameCount, sharedBuffer, &lStatus);            
-        }
+        track = thread->createTrack_l(client, streamType, sampleRate, format,
+                channelCount, frameCount, sharedBuffer, &lStatus);
     }
     if (lStatus == NO_ERROR) {
         trackHandle = new TrackHandle(track);
@@ -414,54 +308,59 @@
     return trackHandle;
 }
 
-uint32_t AudioFlinger::sampleRate(int output) const
+uint32_t AudioFlinger::sampleRate(void *output) const
 {
-#ifdef WITH_A2DP
-     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
-         return mA2dpMixerThread->sampleRate();
-     }
-#endif
-     return mHardwareMixerThread->sampleRate();
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("sampleRate() unknown thread %p", output);
+        return 0;
+    }
+    return thread->sampleRate();
 }
 
-int AudioFlinger::channelCount(int output) const
+int AudioFlinger::channelCount(void *output) const
 {
-#ifdef WITH_A2DP
-     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
-         return mA2dpMixerThread->channelCount();
-     }
-#endif
-     return mHardwareMixerThread->channelCount();
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("channelCount() unknown thread %p", output);
+        return 0;
+    }
+    return thread->channelCount();
 }
 
-int AudioFlinger::format(int output) const
+int AudioFlinger::format(void *output) const
 {
-#ifdef WITH_A2DP
-     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
-         return mA2dpMixerThread->format();
-     }
-#endif
-     return mHardwareMixerThread->format();
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("format() unknown thread %p", output);
+        return 0;
+    }
+    return thread->format();
 }
 
-size_t AudioFlinger::frameCount(int output) const
+size_t AudioFlinger::frameCount(void *output) const
 {
-#ifdef WITH_A2DP
-     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
-         return mA2dpMixerThread->frameCount();
-     }
-#endif
-     return mHardwareMixerThread->frameCount();
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("frameCount() unknown thread %p", output);
+        return 0;
+    }
+    return thread->frameCount();
 }
 
-uint32_t AudioFlinger::latency(int output) const
+uint32_t AudioFlinger::latency(void *output) const
 {
-#ifdef WITH_A2DP
-     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
-         return mA2dpMixerThread->latency();
-     }
-#endif
-     return mHardwareMixerThread->latency();
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("latency() unknown thread %p", output);
+        return 0;
+    }
+    return thread->latency();
 }
 
 status_t AudioFlinger::setMasterVolume(float value)
@@ -478,96 +377,14 @@
         value = 1.0f;
     }
     mHardwareStatus = AUDIO_HW_IDLE;
-    mHardwareMixerThread->setMasterVolume(value);
-#ifdef WITH_A2DP
-    mA2dpMixerThread->setMasterVolume(value);
-#endif
+
+    mMasterVolume = value;
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+       mPlaybackThreads[i]->setMasterVolume(value);
 
     return NO_ERROR;
 }
 
-status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
-{
-    status_t err = NO_ERROR;
-
-    // check calling permissions
-    if (!settingsAllowed()) {
-        return PERMISSION_DENIED;
-    }
-    if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) {
-        LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask);
-        return BAD_VALUE;
-    }
-
-#ifdef WITH_A2DP
-    LOGV("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(),
-            IPCThreadState::self()->getCallingPid());
-    if (mode == AudioSystem::MODE_NORMAL && 
-            (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
-        AutoMutex lock(&mLock);
-
-        bool enableA2dp = false;
-        if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
-            enableA2dp = true;
-        }
-        if (mA2dpDisableCount > 0) {
-            mA2dpSuppressed = enableA2dp;
-        } else {
-            setA2dpEnabled_l(enableA2dp);
-        }
-        LOGV("setOutput done\n");
-    }
-    // setRouting() is always called at least for mode == AudioSystem::MODE_IN_CALL when 
-    // SCO is enabled, whatever current mode is so we can safely handle A2DP disabling only
-    // in this case to avoid doing it several times.
-    if (mode == AudioSystem::MODE_IN_CALL &&
-        (mask & AudioSystem::ROUTE_BLUETOOTH_SCO)) {
-        AutoMutex lock(&mLock);
-        handleRouteDisablesA2dp_l(routes);
-    }
-#endif
-
-    // do nothing if only A2DP routing is affected
-    mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP;
-    if (mask) {
-        AutoMutex lock(mHardwareLock);
-        mHardwareStatus = AUDIO_HW_GET_ROUTING;
-        uint32_t r;
-        err = mAudioHardware->getRouting(mode, &r);
-        if (err == NO_ERROR) {
-            r = (r & ~mask) | (routes & mask);
-            if (mode == AudioSystem::MODE_NORMAL || 
-                (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
-                mSavedRoute = r;
-                r |= mForcedRoute;
-                LOGV("setRouting mSavedRoute %08x mForcedRoute %08x\n", mSavedRoute, mForcedRoute);
-            }
-            mHardwareStatus = AUDIO_HW_SET_ROUTING;
-            err = mAudioHardware->setRouting(mode, r);
-        }
-        mHardwareStatus = AUDIO_HW_IDLE;
-    }
-    return err;
-}
-
-uint32_t AudioFlinger::getRouting(int mode) const
-{
-    uint32_t routes = 0;
-    if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
-        if (mode == AudioSystem::MODE_NORMAL || 
-            (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
-            routes = mSavedRoute;                
-        } else {
-            mHardwareStatus = AUDIO_HW_GET_ROUTING;
-            mAudioHardware->getRouting(mode, &routes);
-            mHardwareStatus = AUDIO_HW_IDLE;
-        }
-    } else {
-        LOGW("Illegal value: getRouting(%d)", mode);
-    }
-    return routes;
-}
-
 status_t AudioFlinger::setMode(int mode)
 {
     // check calling permissions
@@ -586,15 +403,6 @@
     return ret;
 }
 
-int AudioFlinger::getMode() const
-{
-    int mode = AudioSystem::MODE_INVALID;
-    mHardwareStatus = AUDIO_HW_SET_MODE;
-    mAudioHardware->getMode(&mode);
-    mHardwareStatus = AUDIO_HW_IDLE;
-    return mode;
-}
-
 status_t AudioFlinger::setMicMute(bool state)
 {
     // check calling permissions
@@ -624,37 +432,46 @@
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
-    mHardwareMixerThread->setMasterMute(muted);
-#ifdef WITH_A2DP
-    mA2dpMixerThread->setMasterMute(muted);
-#endif
+
+    mMasterMute = muted;
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+       mPlaybackThreads[i]->setMasterMute(muted);
+
     return NO_ERROR;
 }
 
 float AudioFlinger::masterVolume() const
 {
-    return mHardwareMixerThread->masterVolume();
+    return mMasterVolume;
 }
 
 bool AudioFlinger::masterMute() const
 {
-    return mHardwareMixerThread->masterMute();
+    return mMasterMute;
 }
 
-status_t AudioFlinger::setStreamVolume(int stream, float value)
+status_t AudioFlinger::setStreamVolume(int stream, float value, void *output)
 {
     // check calling permissions
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
 
-    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
-        uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
+    if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return BAD_VALUE;
     }
 
+    AutoMutex lock(mLock);
+    PlaybackThread *thread = NULL;
+    if (output) {
+        thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            return BAD_VALUE;
+        }
+    }
+
     status_t ret = NO_ERROR;
-    
+
     if (stream == AudioSystem::VOICE_CALL ||
         stream == AudioSystem::BLUETOOTH_SCO) {
         float hwValue;
@@ -671,18 +488,18 @@
         mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
         ret = mAudioHardware->setVoiceVolume(hwValue);
         mHardwareStatus = AUDIO_HW_IDLE;
-        
-    }
-    
-    mHardwareMixerThread->setStreamVolume(stream, value);
-#ifdef WITH_A2DP
-    mA2dpMixerThread->setStreamVolume(stream, value);
-#endif
 
-    mHardwareMixerThread->setStreamVolume(stream, value);
-#ifdef WITH_A2DP
-    mA2dpMixerThread->setStreamVolume(stream, value);
-#endif
+    }
+
+    mStreamTypes[stream].volume = value;
+
+    if (thread == NULL) {
+        for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+           mPlaybackThreads[i]->setStreamVolume(stream, value);
+
+    } else {
+        thread->setStreamVolume(stream, value);
+    }
 
     return ret;
 }
@@ -694,82 +511,116 @@
         return PERMISSION_DENIED;
     }
 
-    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
+    if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
         uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
         return BAD_VALUE;
     }
 
-#ifdef WITH_A2DP
-    mA2dpMixerThread->setStreamMute(stream, muted);
-#endif
-    if (stream == AudioSystem::MUSIC) 
-    {
-        AutoMutex lock(&mHardwareLock);
-        if (mForcedRoute != 0)
-            mMusicMuteSaved = muted;
-        else
-            mHardwareMixerThread->setStreamMute(stream, muted);
-    } else {
-        mHardwareMixerThread->setStreamMute(stream, muted);
-    }
+    mStreamTypes[stream].mute = muted;
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+       mPlaybackThreads[i]->setStreamMute(stream, muted);
 
     return NO_ERROR;
 }
 
-float AudioFlinger::streamVolume(int stream) const
+float AudioFlinger::streamVolume(int stream, void *output) const
 {
-    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
+    if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return 0.0f;
     }
-    
-    float volume = mHardwareMixerThread->streamVolume(stream); 
+
+    AutoMutex lock(mLock);
+    float volume;
+    if (output) {
+        PlaybackThread *thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            return 0.0f;
+        }
+        volume = thread->streamVolume(stream);
+    } else {
+        volume = mStreamTypes[stream].volume;
+    }
+
     // remove correction applied by setStreamVolume()
     if (stream == AudioSystem::VOICE_CALL) {
         volume = (volume - 0.01) / 0.99 ;
     }
-    
+
     return volume;
 }
 
 bool AudioFlinger::streamMute(int stream) const
 {
-    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
+    if (stream < 0 || stream >= (int)AudioSystem::NUM_STREAM_TYPES) {
         return true;
     }
-    
-    if (stream == AudioSystem::MUSIC && mForcedRoute != 0) 
-    {
-        return mMusicMuteSaved;
-    }
-    return mHardwareMixerThread->streamMute(stream);
+
+    return mStreamTypes[stream].mute;
 }
 
 bool AudioFlinger::isMusicActive() const
 {
     Mutex::Autolock _l(mLock);
- #ifdef WITH_A2DP
-     if (isA2dpEnabled()) {
-         return mA2dpMixerThread->isMusicActive_l();
-     }
- #endif
-    return mHardwareMixerThread->isMusicActive_l();
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
+        if (mPlaybackThreads[i]->isMusicActive()) {
+            return true;
+        }
+    }
+    return false;
 }
 
-status_t AudioFlinger::setParameter(const char* key, const char* value)
+status_t AudioFlinger::setParameters(void *ioHandle, const String8& keyValuePairs)
 {
-    status_t result, result2;
-    AutoMutex lock(mHardwareLock);
-    mHardwareStatus = AUDIO_SET_PARAMETER;
-    
-    LOGV("setParameter() key %s, value %s, tid %d, calling tid %d", key, value, gettid(), IPCThreadState::self()->getCallingPid());
-    result = mAudioHardware->setParameter(key, value);
-    if (mA2dpAudioInterface) {
-        result2 = mA2dpAudioInterface->setParameter(key, value);
-        if (result2)
-            result = result2;
+    status_t result;
+
+    LOGV("setParameters(): io %p, keyvalue %s, tid %d, calling tid %d",
+            ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
     }
-    mHardwareStatus = AUDIO_HW_IDLE;
-    return result;
+
+    // ioHandle == 0 means the parameters are global to the audio hardware interface
+    if (ioHandle == 0) {
+        AutoMutex lock(mHardwareLock);
+        mHardwareStatus = AUDIO_SET_PARAMETER;
+        result = mAudioHardware->setParameters(keyValuePairs);
+        mHardwareStatus = AUDIO_HW_IDLE;
+        return result;
+    }
+
+    // Check if parameters are for an output
+    PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
+    if (playbackThread != NULL) {
+        return playbackThread->setParameters(keyValuePairs);
+    }
+
+    // Check if parameters are for an input
+    RecordThread *recordThread = checkRecordThread_l(ioHandle);
+    if (recordThread != NULL) {
+        return recordThread->setParameters(keyValuePairs);
+    }
+
+    return BAD_VALUE;
+}
+
+String8 AudioFlinger::getParameters(void *ioHandle, const String8& keys)
+{
+//    LOGV("getParameters() io %p, keys %s, tid %d, calling tid %d",
+//            ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
+
+    if (ioHandle == 0) {
+        return mAudioHardware->getParameters(keys);
+    }
+    PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
+    if (playbackThread != NULL) {
+        return playbackThread->getParameters(keys);
+    }
+    RecordThread *recordThread = checkRecordThread_l(ioHandle);
+    if (recordThread != NULL) {
+        return recordThread->getParameters(keys);
+    }
+    return String8("");
 }
 
 size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
@@ -779,7 +630,7 @@
 
 void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
 {
-    
+
     LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
     Mutex::Autolock _l(mLock);
 
@@ -788,12 +639,21 @@
         LOGV("Adding notification client %p", binder.get());
         binder->linkToDeath(this);
         mNotificationClients.add(binder);
-        client->a2dpEnabledChanged(isA2dpEnabled());
+    }
+
+    // the config change is always sent from playback or record threads to avoid deadlock
+    // with AudioSystem::gLock
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        mPlaybackThreads[i]->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
+    }
+
+    for (size_t i = 0; i < mRecordThreads.size(); i++) {
+        mRecordThreads[i]->sendConfigEvent(AudioSystem::INPUT_OPENED);
     }
 }
 
 void AudioFlinger::binderDied(const wp<IBinder>& who) {
-    
+
     LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
     Mutex::Autolock _l(mLock);
 
@@ -808,6 +668,17 @@
     }
 }
 
+void AudioFlinger::audioConfigChanged(int event, void *param1, void *param2) {
+    Mutex::Autolock _l(mLock);
+    size_t size = mNotificationClients.size();
+    for (size_t i = 0; i < size; i++) {
+        sp<IBinder> binder = mNotificationClients.itemAt(i);
+        LOGV("audioConfigChanged() Notifying change to client %p", binder.get());
+        sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
+        client->ioConfigChanged(event, param1, param2);
+    }
+}
+
 void AudioFlinger::removeClient(pid_t pid)
 {
     LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
@@ -815,147 +686,139 @@
     mClients.removeItem(pid);
 }
 
-bool AudioFlinger::isA2dpEnabled() const
+// ----------------------------------------------------------------------------
+
+AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger)
+    :   Thread(false),
+        mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
+        mFormat(0), mFrameSize(1), mNewParameters(String8("")), mStandby(false)
 {
-    return mA2dpEnabled;
 }
 
-void AudioFlinger::handleForcedSpeakerRoute(int command)
+AudioFlinger::ThreadBase::~ThreadBase()
 {
-    switch(command) {
-    case ACTIVE_TRACK_ADDED:
-        {
-            AutoMutex lock(mHardwareLock);
-            if (mForcedSpeakerCount++ == 0) {
-                if (mForcedRoute == 0) {
-                    mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC);
-                    LOGV("++mForcedSpeakerCount == 0, mMusicMuteSaved = %d, mRouteRestoreTime = %d", mMusicMuteSaved, mRouteRestoreTime);
-                    if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
-                        LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
-                        mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
-                        usleep(mHardwareMixerThread->latency()*1000);
-                        mHardwareStatus = AUDIO_HW_SET_ROUTING;
-                        mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
-                        mHardwareStatus = AUDIO_HW_IDLE;
-                        // delay track start so that audio hardware has time to siwtch routes
-                        usleep(kStartSleepTime);
-                    }
-                }
-                mForcedRoute = AudioSystem::ROUTE_SPEAKER;
-                mRouteRestoreTime = 0;
-            }
-            LOGV("mForcedSpeakerCount incremented to %d", mForcedSpeakerCount);
-        }
-        break;
-    case ACTIVE_TRACK_REMOVED:
-        {
-            AutoMutex lock(mHardwareLock);
-            if (mForcedSpeakerCount > 0){
-                if (--mForcedSpeakerCount == 0) {
-                    mRouteRestoreTime = systemTime() + milliseconds(kStopSleepTime/1000);
-                }
-                LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount);
-            } else {
-                LOGE("mForcedSpeakerCount is already zero");
-            }
-        }
-        break;
-    case CHECK_ROUTE_RESTORE_TIME:
-    case FORCE_ROUTE_RESTORE:
-        if (mRouteRestoreTime) {
-            AutoMutex lock(mHardwareLock);
-            if (mRouteRestoreTime && 
-               (systemTime() > mRouteRestoreTime || command == FORCE_ROUTE_RESTORE)) {
-                mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, mMusicMuteSaved);
-                mForcedRoute = 0;
-                if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
-                    mHardwareStatus = AUDIO_HW_SET_ROUTING;
-                    mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute);
-                    mHardwareStatus = AUDIO_HW_IDLE;
-                    LOGV("Route forced to Speaker OFF %08x", mSavedRoute);
-                }
-                mRouteRestoreTime = 0;
-            }
-        }
-        break;
-    }
 }
 
-#ifdef WITH_A2DP
-// handleRouteDisablesA2dp_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::handleRouteDisablesA2dp_l(int routes)
+void AudioFlinger::ThreadBase::exit()
 {
-   if (routes & AudioSystem::ROUTE_BLUETOOTH_SCO) {
-        if (mA2dpDisableCount++ == 0) {
-            if (mA2dpEnabled) {
-                setA2dpEnabled_l(false);
-                mA2dpSuppressed = true;
-            }
-        }
-        LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount);
-   } else {
-        if (mA2dpDisableCount > 0) {
-            if (--mA2dpDisableCount == 0) {
-                if (mA2dpSuppressed) {
-                    setA2dpEnabled_l(true);
-                    mA2dpSuppressed = false;
-                }
-            }
-            LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount);
-        } else {
-            LOGV("mA2dpDisableCount is already zero");
-        }
+    // keep a strong ref on ourself so that we want get
+    // destroyed in the middle of requestExitAndWait()
+    sp <ThreadBase> strongMe = this;
+
+    LOGV("ThreadBase::exit");
+    {
+        AutoMutex lock(&mLock);
+        requestExit();
+        mWaitWorkCV.signal();
     }
+    requestExitAndWait();
 }
-#endif
+
+uint32_t AudioFlinger::ThreadBase::sampleRate() const
+{
+    return mSampleRate;
+}
+
+int AudioFlinger::ThreadBase::channelCount() const
+{
+    return mChannelCount;
+}
+
+int AudioFlinger::ThreadBase::format() const
+{
+    return mFormat;
+}
+
+size_t AudioFlinger::ThreadBase::frameCount() const
+{
+    return mFrameCount;
+}
+
+status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
+{
+    status_t result;
+
+    Mutex::Autolock _l(mLock);
+    mNewParameters = keyValuePairs;
+
+    mWaitWorkCV.signal();
+    mParamCond.wait(mLock);
+
+    return mParamStatus;
+}
+
+void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
+{
+    Mutex::Autolock _l(mLock);
+    ConfigEvent *configEvent = new ConfigEvent();
+    configEvent->mEvent = event;
+    configEvent->mParam = param;
+    mConfigEvents.add(configEvent);
+    LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
+    mWaitWorkCV.signal();
+}
+
+void AudioFlinger::ThreadBase::processConfigEvents()
+{
+    mLock.lock();
+    while(!mConfigEvents.isEmpty()) {
+        LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
+        ConfigEvent *configEvent = mConfigEvents[0];
+        mConfigEvents.removeAt(0);
+        // release mLock because audioConfigChanged() will call
+        // Audioflinger::audioConfigChanged() which locks AudioFlinger mLock thus creating
+        // potential cross deadlock between AudioFlinger::mLock and mLock
+        mLock.unlock();
+        audioConfigChanged(configEvent->mEvent, configEvent->mParam);
+        delete configEvent;
+        mLock.lock();
+    }
+    mLock.unlock();
+}
+
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType)
-    :   Thread(false),
-        mAudioFlinger(audioFlinger), mAudioMixer(0), mOutput(output), mOutputType(outputType), 
-        mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
-        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
-        mInWrite(false)
+AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
+    :   ThreadBase(audioFlinger),
+        mMixBuffer(0), mSuspended(false), mBytesWritten(0), mOutput(output),
+        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
 {
-    mSampleRate = output->sampleRate();
-    mChannelCount = output->channelCount();
+    readOutputParameters();
 
-    // FIXME - Current mixer implementation only supports stereo output
-    if (mChannelCount == 1) {
-        LOGE("Invalid audio hardware channel count");
+    mMasterVolume = mAudioFlinger->masterVolume();
+    mMasterMute = mAudioFlinger->masterMute();
+
+    for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
+        mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
+        mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
     }
-
-    mFormat = output->format();
-    mFrameCount = output->bufferSize() / output->channelCount() / sizeof(int16_t);
-    mAudioMixer = new AudioMixer(mFrameCount, output->sampleRate());
-
-    // FIXME - Current mixer implementation only supports stereo output: Always
-    // Allocate a stereo buffer even if HW output is mono.
-    mMixBuffer = new int16_t[mFrameCount * 2];
-    memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
+    // notify client processes that a new input has been opened
+    sendConfigEvent(AudioSystem::OUTPUT_OPENED);
 }
 
-AudioFlinger::MixerThread::~MixerThread()
+AudioFlinger::PlaybackThread::~PlaybackThread()
 {
     delete [] mMixBuffer;
-    delete mAudioMixer;
+    if (mType != DUPLICATING) {
+        mAudioFlinger->mAudioHardware->closeOutputStream(mOutput);
+    }
 }
 
-status_t AudioFlinger::MixerThread::dump(int fd, const Vector<String16>& args)
+status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
 {
     dumpInternals(fd, args);
     dumpTracks(fd, args);
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MixerThread::dumpTracks(int fd, const Vector<String16>& args)
+status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
 
-    snprintf(buffer, SIZE, "Output %d mixer thread tracks\n", mOutputType);
+    snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
     result.append(buffer);
     result.append("   Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
     for (size_t i = 0; i < mTracks.size(); ++i) {
@@ -966,7 +829,7 @@
         }
     }
 
-    snprintf(buffer, SIZE, "Output %d mixer thread active tracks\n", mOutputType);
+    snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
     result.append(buffer);
     result.append("   Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
     for (size_t i = 0; i < mActiveTracks.size(); ++i) {
@@ -983,15 +846,13 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
+status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
 
-    snprintf(buffer, SIZE, "Output %d mixer thread internals\n", mOutputType);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
+    snprintf(buffer, SIZE, "Output thread %p internals\n", this);
     result.append(buffer);
     snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
     result.append(buffer);
@@ -1008,275 +869,28 @@
 }
 
 // Thread virtuals
-bool AudioFlinger::MixerThread::threadLoop()
-{
-    unsigned long sleepTime = kBufferRecoveryInUsecs;
-    int16_t* curBuf = mMixBuffer;
-    Vector< sp<Track> > tracksToRemove;
-    size_t enabledTracks = 0;
-    nsecs_t standbyTime = systemTime();   
-    size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
-    nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
-
-#ifdef WITH_A2DP
-    bool outputTrackActive = false;
-#endif
-
-    do {
-        enabledTracks = 0;
-        { // scope for the AudioFlinger::mLock
-        
-            Mutex::Autolock _l(mAudioFlinger->mLock);
-
-#ifdef WITH_A2DP
-            if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) {
-                if (outputTrackActive) {
-                    mAudioFlinger->mLock.unlock();
-                    mOutputTrack->stop();
-                    mAudioFlinger->mLock.lock();
-                    outputTrackActive = false;
-                }
-            }
-            mAudioFlinger->checkA2dpEnabledChange_l();
-#endif
-
-            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
-
-            // put audio hardware into standby after short delay
-            if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
-                // wait until we have something to do...
-                LOGV("Audio hardware entering standby, output %d\n", mOutputType);
-                if (!mStandby) {
-                    mOutput->standby();
-                    mStandby = true;
-                }
-                
-#ifdef WITH_A2DP
-                if (outputTrackActive) {
-                    mAudioFlinger->mLock.unlock();
-                    mOutputTrack->stop();
-                    mAudioFlinger->mLock.lock();
-                    outputTrackActive = false;
-                }
-#endif
-                if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
-                    mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE);
-                }                
-                // we're about to wait, flush the binder command buffer
-                IPCThreadState::self()->flushCommands();
-                mAudioFlinger->mWaitWorkCV.wait(mAudioFlinger->mLock);
-                LOGV("Audio hardware exiting standby, output %d\n", mOutputType);
-                
-                if (mMasterMute == false) {
-                    char value[PROPERTY_VALUE_MAX];
-                    property_get("ro.audio.silent", value, "0");
-                    if (atoi(value)) {
-                        LOGD("Silence is golden");
-                        setMasterMute(true);
-                    }                    
-                }
-                
-                standbyTime = systemTime() + kStandbyTimeInNsecs;
-                continue;
-            }
-
-            // Forced route to speaker is handled by hardware mixer thread
-            if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
-                mAudioFlinger->handleForcedSpeakerRoute(CHECK_ROUTE_RESTORE_TIME);
-            }
-
-            // find out which tracks need to be processed
-            size_t count = activeTracks.size();
-            for (size_t i=0 ; i<count ; i++) {
-                sp<Track> t = activeTracks[i].promote();
-                if (t == 0) continue;
-
-                Track* const track = t.get();
-                audio_track_cblk_t* cblk = track->cblk();
-
-                // The first time a track is added we wait
-                // for all its buffers to be filled before processing it
-                mAudioMixer->setActiveTrack(track->name());
-                if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
-                        !track->isPaused())
-                {
-                    //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
-
-                    // compute volume for this track
-                    int16_t left, right;
-                    if (track->isMuted() || mMasterMute || track->isPausing()) {
-                        left = right = 0;
-                        if (track->isPausing()) {
-                            LOGV("paused(%d)", track->name());
-                            track->setPaused();
-                        }
-                    } else {
-                        float typeVolume = mStreamTypes[track->type()].volume;
-                        float v = mMasterVolume * typeVolume;
-                        float v_clamped = v * cblk->volume[0];
-                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
-                        left = int16_t(v_clamped);
-                        v_clamped = v * cblk->volume[1];
-                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
-                        right = int16_t(v_clamped);
-                    }
-
-                    // XXX: these things DON'T need to be done each time
-                    mAudioMixer->setBufferProvider(track);
-                    mAudioMixer->enable(AudioMixer::MIXING);
-
-                    int param;
-                    if ( track->mFillingUpStatus == Track::FS_FILLED) {
-                        // no ramp for the first volume setting
-                        track->mFillingUpStatus = Track::FS_ACTIVE;
-                        if (track->mState == TrackBase::RESUMING) {
-                            track->mState = TrackBase::ACTIVE;
-                            param = AudioMixer::RAMP_VOLUME;
-                        } else {
-                            param = AudioMixer::VOLUME;
-                        }
-                    } else {
-                        param = AudioMixer::RAMP_VOLUME;
-                    }
-                    mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
-                    mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
-                    mAudioMixer->setParameter(
-                        AudioMixer::TRACK,
-                        AudioMixer::FORMAT, track->format());
-                    mAudioMixer->setParameter(
-                        AudioMixer::TRACK,
-                        AudioMixer::CHANNEL_COUNT, track->channelCount());
-                    mAudioMixer->setParameter(
-                        AudioMixer::RESAMPLE,
-                        AudioMixer::SAMPLE_RATE,
-                        int(cblk->sampleRate));
-
-                    // reset retry count
-                    track->mRetryCount = kMaxTrackRetries;
-                    enabledTracks++;
-                } else {
-                    //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
-                    if (track->isStopped()) {
-                        track->reset();
-                    }
-                    if (track->isTerminated() || track->isStopped() || track->isPaused()) {
-                        // We have consumed all the buffers of this track.
-                        // Remove it from the list of active tracks.
-                        LOGV("remove(%d) from active list", track->name());
-                        tracksToRemove.add(track);
-                    } else {
-                        // No buffers for this track. Give it a few chances to
-                        // fill a buffer, then remove it from active list.
-                        if (--(track->mRetryCount) <= 0) {
-                            LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
-                            tracksToRemove.add(track);
-                        }
-                    }
-                    // LOGV("disable(%d)", track->name());
-                    mAudioMixer->disable(AudioMixer::MIXING);
-                }
-            }
-
-            // remove all the tracks that need to be...
-            count = tracksToRemove.size();
-            if (UNLIKELY(count)) {
-                for (size_t i=0 ; i<count ; i++) {
-                    const sp<Track>& track = tracksToRemove[i];
-                    removeActiveTrack_l(track);
-                    if (track->isTerminated()) {
-                        mTracks.remove(track);
-                        deleteTrackName_l(track->mName);
-                    }
-                }
-            }
-       }
-        
-        if (LIKELY(enabledTracks)) {
-            // mix buffers...
-            mAudioMixer->process(curBuf);
-
-#ifdef WITH_A2DP
-            if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
-                if (!outputTrackActive) {
-                    LOGV("starting output track in mixer for output %d", mOutputType);
-                    mOutputTrack->start();
-                    outputTrackActive = true;
-                }
-                mOutputTrack->write(curBuf, mFrameCount);
-            }
-#endif
-
-            // output audio to hardware
-            mLastWriteTime = systemTime();
-            mInWrite = true;
-            mOutput->write(curBuf, mixBufferSize);
-            mNumWrites++;
-            mInWrite = false;
-            mStandby = false;
-            nsecs_t temp = systemTime();
-            standbyTime = temp + kStandbyTimeInNsecs;
-            nsecs_t delta = temp - mLastWriteTime;
-            if (delta > maxPeriod) {
-                LOGW("write blocked for %llu msecs", ns2ms(delta));
-                mNumDelayedWrites++;
-            }
-            sleepTime = kBufferRecoveryInUsecs;
-        } else {         
-#ifdef WITH_A2DP
-            if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
-                if (outputTrackActive) {
-                    mOutputTrack->write(curBuf, 0);
-                    if (mOutputTrack->bufferQueueEmpty()) {
-                        mOutputTrack->stop();
-                        outputTrackActive = false;
-                    } else {
-                        standbyTime = systemTime() + kStandbyTimeInNsecs;
-                    }
-                }
-            }
-#endif
-            // There was nothing to mix this round, which means all
-            // active tracks were late. Sleep a little bit to give
-            // them another chance. If we're too late, the audio
-            // hardware will zero-fill for us.
-            //LOGV("no buffers - usleep(%lu)", sleepTime);
-            usleep(sleepTime);
-            if (sleepTime < kMaxBufferRecoveryInUsecs) {
-                sleepTime += kBufferRecoveryInUsecs;
-            }
-        }
-
-        // finally let go of all our tracks, without the lock held
-        // since we can't guarantee the destructors won't acquire that
-        // same lock.
-        tracksToRemove.clear();
-    } while (true);
-
-    return false;
-}
-
-status_t AudioFlinger::MixerThread::readyToRun()
+status_t AudioFlinger::PlaybackThread::readyToRun()
 {
     if (mSampleRate == 0) {
         LOGE("No working audio driver found.");
         return NO_INIT;
     }
-    LOGI("AudioFlinger's thread ready to run for output %d", mOutputType);
+    LOGI("AudioFlinger's thread %p ready to run", this);
     return NO_ERROR;
 }
 
-void AudioFlinger::MixerThread::onFirstRef()
+void AudioFlinger::PlaybackThread::onFirstRef()
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
 
-    snprintf(buffer, SIZE, "Mixer Thread for output %d", mOutputType);
+    snprintf(buffer, SIZE, "Playback Thread %p", this);
 
     run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
 }
 
-// MixerThread::createTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::MixerThread::Track>  AudioFlinger::MixerThread::createTrack_l(
+// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
+sp<AudioFlinger::PlaybackThread::Track>  AudioFlinger::PlaybackThread::createTrack_l(
         const sp<AudioFlinger::Client>& client,
         int streamType,
         uint32_t sampleRate,
@@ -1288,28 +902,39 @@
 {
     sp<Track> track;
     status_t lStatus;
-    
-    // Resampler implementation limits input sampling rate to 2 x output sampling rate.
-    if (sampleRate > mSampleRate*2) {
-        LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
-        lStatus = BAD_VALUE;
-        goto Exit;
+
+    if (mType == DIRECT) {
+        if (sampleRate != mSampleRate || format != mFormat || channelCount != mChannelCount) {
+            LOGE("createTrack_l() Bad parameter:  sampleRate %d format %d, channelCount %d for output %p",
+                 sampleRate, format, channelCount, mOutput);
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
+    } else {
+        // Resampler implementation limits input sampling rate to 2 x output sampling rate.
+        if (sampleRate > mSampleRate*2) {
+            LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
     }
 
-
-    if (mSampleRate == 0) {
+    if (mOutput == 0) {
         LOGE("Audio driver not initialized.");
         lStatus = NO_INIT;
         goto Exit;
     }
 
-    track = new Track(this, client, streamType, sampleRate, format,
-            channelCount, frameCount, sharedBuffer);
-    if (track->getCblk() == NULL) {
-        lStatus = NO_MEMORY;
-        goto Exit;
+    { // scope for mLock
+        Mutex::Autolock _l(mLock);
+        track = new Track(this, client, streamType, sampleRate, format,
+                channelCount, frameCount, sharedBuffer);
+        if (track->getCblk() == NULL) {
+            lStatus = NO_MEMORY;
+            goto Exit;
+        }
+        mTracks.add(track);
     }
-    mTracks.add(track);
     lStatus = NO_ERROR;
 
 Exit:
@@ -1319,87 +944,7 @@
     return track;
 }
 
-// getTracks_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::getTracks_l(
-        SortedVector < sp<Track> >& tracks,
-        SortedVector < wp<Track> >& activeTracks)
-{
-    size_t size = mTracks.size();
-    LOGV ("MixerThread::getTracks_l() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType,  mTracks.size(), mActiveTracks.size());
-    for (size_t i = 0; i < size; i++) {
-        sp<Track> t = mTracks[i];
-        if (AudioSystem::routedToA2dpOutput(t->mStreamType)) {
-            tracks.add(t);
-            int j = mActiveTracks.indexOf(t);
-            if (j >= 0) {
-                t = mActiveTracks[j].promote();
-                if (t != NULL) {
-                    activeTracks.add(t);                                    
-                }                            
-            }
-        }
-    }
-
-    size = activeTracks.size();
-    for (size_t i = 0; i < size; i++) {
-        removeActiveTrack_l(activeTracks[i]);
-    }
-    
-    size = tracks.size();
-    for (size_t i = 0; i < size; i++) {
-        sp<Track> t = tracks[i];
-        mTracks.remove(t);
-        deleteTrackName_l(t->name());
-    }
-}
-
-// putTracks_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::putTracks_l(
-        SortedVector < sp<Track> >& tracks,
-        SortedVector < wp<Track> >& activeTracks)
-{
-
-    LOGV ("MixerThread::putTracks_l() for output %d, tracks.size %d, activeTracks.size %d", mOutputType,  tracks.size(), activeTracks.size());
-
-    size_t size = tracks.size();
-    for (size_t i = 0; i < size ; i++) {
-        sp<Track> t = tracks[i];
-        int name = getTrackName_l();
-
-        if (name < 0) return;
-        
-        t->mName = name;
-        t->mMixerThread = this;
-        mTracks.add(t);
-
-        int j = activeTracks.indexOf(t);
-        if (j >= 0) {
-            addActiveTrack_l(t);
-        }            
-    }
-}
-
-uint32_t AudioFlinger::MixerThread::sampleRate() const
-{
-    return mSampleRate;
-}
-
-int AudioFlinger::MixerThread::channelCount() const
-{
-    return mChannelCount;
-}
-
-int AudioFlinger::MixerThread::format() const
-{
-    return mFormat;
-}
-
-size_t AudioFlinger::MixerThread::frameCount() const
-{
-    return mFrameCount;
-}
-
-uint32_t AudioFlinger::MixerThread::latency() const
+uint32_t AudioFlinger::PlaybackThread::latency() const
 {
     if (mOutput) {
         return mOutput->latency();
@@ -1409,66 +954,66 @@
     }
 }
 
-status_t AudioFlinger::MixerThread::setMasterVolume(float value)
+status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
 {
     mMasterVolume = value;
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MixerThread::setMasterMute(bool muted)
+status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
 {
     mMasterMute = muted;
     return NO_ERROR;
 }
 
-float AudioFlinger::MixerThread::masterVolume() const
+float AudioFlinger::PlaybackThread::masterVolume() const
 {
     return mMasterVolume;
 }
 
-bool AudioFlinger::MixerThread::masterMute() const
+bool AudioFlinger::PlaybackThread::masterMute() const
 {
     return mMasterMute;
 }
 
-status_t AudioFlinger::MixerThread::setStreamVolume(int stream, float value)
+status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
 {
     mStreamTypes[stream].volume = value;
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MixerThread::setStreamMute(int stream, bool muted)
+status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
 {
     mStreamTypes[stream].mute = muted;
     return NO_ERROR;
 }
 
-float AudioFlinger::MixerThread::streamVolume(int stream) const
+float AudioFlinger::PlaybackThread::streamVolume(int stream) const
 {
     return mStreamTypes[stream].volume;
 }
 
-bool AudioFlinger::MixerThread::streamMute(int stream) const
+bool AudioFlinger::PlaybackThread::streamMute(int stream) const
 {
     return mStreamTypes[stream].mute;
 }
 
-// isMusicActive_l() must be called with AudioFlinger::mLock held
-bool AudioFlinger::MixerThread::isMusicActive_l() const
+bool AudioFlinger::PlaybackThread::isMusicActive() const
 {
+    Mutex::Autolock _l(mLock);
     size_t count = mActiveTracks.size();
     for (size_t i = 0 ; i < count ; ++i) {
         sp<Track> t = mActiveTracks[i].promote();
         if (t == 0) continue;
         Track* const track = t.get();
-        if (t->mStreamType == AudioSystem::MUSIC)
+        if (t->type() == AudioSystem::MUSIC)
             return true;
     }
     return false;
 }
 
-// addTrack_l() must be called with AudioFlinger::mLock held
-status_t AudioFlinger::MixerThread::addTrack_l(const sp<Track>& track)
+// addTrack_l() must be called with ThreadBase::mLock held
+status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
 {
     status_t status = ALREADY_EXISTS;
 
@@ -1489,18 +1034,18 @@
         // effectively get the latency it requested.
         track->mFillingUpStatus = Track::FS_FILLING;
         track->mResetDone = false;
-        addActiveTrack_l(track);
+        mActiveTracks.add(track);
         status = NO_ERROR;
     }
-    
+
     LOGV("mWaitWorkCV.broadcast");
-    mAudioFlinger->mWaitWorkCV.broadcast();
+    mWaitWorkCV.broadcast();
 
     return status;
 }
 
-// destroyTrack_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track)
+// destroyTrack_l() must be called with ThreadBase::mLock held
+void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
 {
     track->mState = TrackBase::TERMINATED;
     if (mActiveTracks.indexOf(track) < 0) {
@@ -1510,62 +1055,893 @@
     }
 }
 
-// addActiveTrack_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t)
+String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
 {
-    mActiveTracks.add(t);
+    return mOutput->getParameters(keys);
+}
 
-    // Force routing to speaker for certain stream types
-    // The forced routing to speaker is managed by hardware mixer
-    if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
-        sp<Track> track = t.promote();
-        if (track == NULL) return;
-   
-        if (streamForcedToSpeaker(track->type())) {
-            mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED);
-        }        
+void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
+    AudioSystem::OutputDescriptor desc;
+    void *param2 = 0;
+
+    LOGV("PlaybackThread::audioConfigChanged, thread %p, event %d, param %d", this, event, param);
+
+    switch (event) {
+    case AudioSystem::OUTPUT_OPENED:
+    case AudioSystem::OUTPUT_CONFIG_CHANGED:
+        desc.channels = mChannelCount;
+        desc.samplingRate = mSampleRate;
+        desc.format = mFormat;
+        desc.frameCount = mFrameCount;
+        desc.latency = latency();
+        param2 = &desc;
+        break;
+
+    case AudioSystem::STREAM_CONFIG_CHANGED:
+        param2 = &param;
+    case AudioSystem::OUTPUT_CLOSED:
+    default:
+        break;
+    }
+    mAudioFlinger->audioConfigChanged(event, this, param2);
+}
+
+void AudioFlinger::PlaybackThread::readOutputParameters()
+{
+    mSampleRate = mOutput->sampleRate();
+    mChannelCount = AudioSystem::popCount(mOutput->channels());
+
+    mFormat = mOutput->format();
+    mFrameSize = mOutput->frameSize();
+    mFrameCount = mOutput->bufferSize() / mFrameSize;
+
+    mMinBytesToWrite = (mOutput->latency() * mSampleRate * mFrameSize) / 1000;
+    // FIXME - Current mixer implementation only supports stereo output: Always
+    // Allocate a stereo buffer even if HW output is mono.
+    if (mMixBuffer != NULL) delete mMixBuffer;
+    mMixBuffer = new int16_t[mFrameCount * 2];
+    memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
+    :   PlaybackThread(audioFlinger, output),
+        mAudioMixer(0)
+{
+    mType = PlaybackThread::MIXER;
+    mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
+
+    // FIXME - Current mixer implementation only supports stereo output
+    if (mChannelCount == 1) {
+        LOGE("Invalid audio hardware channel count");
     }
 }
 
-// removeActiveTrack_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t)
+AudioFlinger::MixerThread::~MixerThread()
 {
-    mActiveTracks.remove(t);
+    delete mAudioMixer;
+}
 
-    // Force routing to speaker for certain stream types
-    // The forced routing to speaker is managed by hardware mixer
-    if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
-        sp<Track> track = t.promote();
-        if (track == NULL) return;
+bool AudioFlinger::MixerThread::threadLoop()
+{
+    unsigned long sleepTime = kBufferRecoveryInUsecs;
+    int16_t* curBuf = mMixBuffer;
+    Vector< sp<Track> > tracksToRemove;
+    size_t enabledTracks = 0;
+    nsecs_t standbyTime = systemTime();
+    size_t mixBufferSize = mFrameCount * mFrameSize;
+    nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
 
-        if (streamForcedToSpeaker(track->type())) {
-            mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED);
+    while (!exitPending())
+    {
+        processConfigEvents();
+
+        enabledTracks = 0;
+        { // scope for mLock
+
+            Mutex::Autolock _l(mLock);
+
+            if (checkForNewParameters_l()) {
+                mixBufferSize = mFrameCount * mFrameSize;
+                maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
+            }
+
+            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
+
+            // put audio hardware into standby after short delay
+            if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
+                        mSuspended) {
+                if (!mStandby) {
+                    LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
+                    mOutput->standby();
+                    mStandby = true;
+                    mBytesWritten = 0;
+                }
+
+                if (!activeTracks.size() && mConfigEvents.isEmpty()) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+
+                    if (exitPending()) break;
+
+                    // wait until we have something to do...
+                    LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
+                    mWaitWorkCV.wait(mLock);
+                    LOGV("MixerThread %p TID %d waking up\n", this, gettid());
+
+                    if (mMasterMute == false) {
+                        char value[PROPERTY_VALUE_MAX];
+                        property_get("ro.audio.silent", value, "0");
+                        if (atoi(value)) {
+                            LOGD("Silence is golden");
+                            setMasterMute(true);
+                        }
+                    }
+
+                    standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    continue;
+                }
+            }
+
+            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
+       }
+
+        if (LIKELY(enabledTracks)) {
+            // mix buffers...
+            mAudioMixer->process(curBuf);
+
+            // output audio to hardware
+            if (mSuspended) {
+                usleep(kMaxBufferRecoveryInUsecs);
+            } else {
+                mLastWriteTime = systemTime();
+                mInWrite = true;
+                int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
+                if (bytesWritten > 0) mBytesWritten += bytesWritten;
+                mNumWrites++;
+                mInWrite = false;
+                mStandby = false;
+                nsecs_t temp = systemTime();
+                standbyTime = temp + kStandbyTimeInNsecs;
+                nsecs_t delta = temp - mLastWriteTime;
+                if (delta > maxPeriod) {
+                    LOGW("write blocked for %llu msecs", ns2ms(delta));
+                    mNumDelayedWrites++;
+                }
+                sleepTime = kBufferRecoveryInUsecs;
+            }
+        } else {
+            // There was nothing to mix this round, which means all
+            // active tracks were late. Sleep a little bit to give
+            // them another chance. If we're too late, the audio
+            // hardware will zero-fill for us.
+            // LOGV("thread %p no buffers - usleep(%lu)", this, sleepTime);
+            usleep(sleepTime);
+            if (sleepTime < kMaxBufferRecoveryInUsecs) {
+                sleepTime += kBufferRecoveryInUsecs;
+            }
+        }
+
+        // finally let go of all our tracks, without the lock held
+        // since we can't guarantee the destructors won't acquire that
+        // same lock.
+        tracksToRemove.clear();
+    }
+
+    if (!mStandby) {
+        mOutput->standby();
+    }
+    sendConfigEvent(AudioSystem::OUTPUT_CLOSED);
+    processConfigEvents();
+
+    LOGV("MixerThread %p exiting", this);
+    return false;
+}
+
+// prepareTracks_l() must be called with ThreadBase::mLock held
+size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
+{
+
+    size_t enabledTracks = 0;
+    // find out which tracks need to be processed
+    size_t count = activeTracks.size();
+    for (size_t i=0 ; i<count ; i++) {
+        sp<Track> t = activeTracks[i].promote();
+        if (t == 0) continue;
+
+        Track* const track = t.get();
+        audio_track_cblk_t* cblk = track->cblk();
+
+        // The first time a track is added we wait
+        // for all its buffers to be filled before processing it
+        mAudioMixer->setActiveTrack(track->name());
+        if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
+                !track->isPaused())
+        {
+            //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
+
+            // compute volume for this track
+            int16_t left, right;
+            if (track->isMuted() || mMasterMute || track->isPausing() ||
+                mStreamTypes[track->type()].mute) {
+                left = right = 0;
+                if (track->isPausing()) {
+                    track->setPaused();
+                }
+            } else {
+                float typeVolume = mStreamTypes[track->type()].volume;
+                float v = mMasterVolume * typeVolume;
+                float v_clamped = v * cblk->volume[0];
+                if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                left = int16_t(v_clamped);
+                v_clamped = v * cblk->volume[1];
+                if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                right = int16_t(v_clamped);
+            }
+
+            // XXX: these things DON'T need to be done each time
+            mAudioMixer->setBufferProvider(track);
+            mAudioMixer->enable(AudioMixer::MIXING);
+
+            int param;
+            if ( track->mFillingUpStatus == Track::FS_FILLED) {
+                // no ramp for the first volume setting
+                track->mFillingUpStatus = Track::FS_ACTIVE;
+                if (track->mState == TrackBase::RESUMING) {
+                    track->mState = TrackBase::ACTIVE;
+                    param = AudioMixer::RAMP_VOLUME;
+                } else {
+                    param = AudioMixer::VOLUME;
+                }
+            } else {
+                param = AudioMixer::RAMP_VOLUME;
+            }
+            mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
+            mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
+            mAudioMixer->setParameter(
+                AudioMixer::TRACK,
+                AudioMixer::FORMAT, track->format());
+            mAudioMixer->setParameter(
+                AudioMixer::TRACK,
+                AudioMixer::CHANNEL_COUNT, track->channelCount());
+            mAudioMixer->setParameter(
+                AudioMixer::RESAMPLE,
+                AudioMixer::SAMPLE_RATE,
+                int(cblk->sampleRate));
+
+            // reset retry count
+            track->mRetryCount = kMaxTrackRetries;
+            enabledTracks++;
+        } else {
+            //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
+            if (track->isStopped()) {
+                track->reset();
+            }
+            if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+                // We have consumed all the buffers of this track.
+                // Remove it from the list of active tracks.
+                tracksToRemove->add(track);
+                mAudioMixer->disable(AudioMixer::MIXING);
+            } else {
+                // No buffers for this track. Give it a few chances to
+                // fill a buffer, then remove it from active list.
+                if (--(track->mRetryCount) <= 0) {
+                    LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
+                    tracksToRemove->add(track);
+                }
+                // For tracks using static shared memry buffer, make sure that we have
+                // written enough data to audio hardware before disabling the track
+                // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
+                // don't care about code removing track from active list above.
+                if ((track->mSharedBuffer == 0) || (mBytesWritten >= mMinBytesToWrite)) {
+                    mAudioMixer->disable(AudioMixer::MIXING);
+                } else {
+                    enabledTracks++;
+                }
+            }
+        }
+    }
+
+    // remove all the tracks that need to be...
+    count = tracksToRemove->size();
+    if (UNLIKELY(count)) {
+        for (size_t i=0 ; i<count ; i++) {
+            const sp<Track>& track = tracksToRemove->itemAt(i);
+            mActiveTracks.remove(track);
+            if (track->isTerminated()) {
+                mTracks.remove(track);
+                deleteTrackName_l(track->mName);
+            }
+        }
+    }
+
+    return enabledTracks;
+}
+
+void AudioFlinger::MixerThread::getTracks(
+        SortedVector < sp<Track> >& tracks,
+        SortedVector < wp<Track> >& activeTracks,
+        int streamType)
+{
+    LOGV ("MixerThread::getTracks() mixer %p, mTracks.size %d, mActiveTracks.size %d", this,  mTracks.size(), mActiveTracks.size());
+    Mutex::Autolock _l(mLock);
+    size_t size = mTracks.size();
+    for (size_t i = 0; i < size; i++) {
+        sp<Track> t = mTracks[i];
+        if (t->type() == streamType) {
+            tracks.add(t);
+            int j = mActiveTracks.indexOf(t);
+            if (j >= 0) {
+                t = mActiveTracks[j].promote();
+                if (t != NULL) {
+                    activeTracks.add(t);
+                }
+            }
+        }
+    }
+
+    size = activeTracks.size();
+    for (size_t i = 0; i < size; i++) {
+        mActiveTracks.remove(activeTracks[i]);
+    }
+
+    size = tracks.size();
+    for (size_t i = 0; i < size; i++) {
+        sp<Track> t = tracks[i];
+        mTracks.remove(t);
+        deleteTrackName_l(t->name());
+    }
+}
+
+void AudioFlinger::MixerThread::putTracks(
+        SortedVector < sp<Track> >& tracks,
+        SortedVector < wp<Track> >& activeTracks)
+{
+    LOGV ("MixerThread::putTracks() mixer %p, tracks.size %d, activeTracks.size %d", this,  tracks.size(), activeTracks.size());
+    Mutex::Autolock _l(mLock);
+    size_t size = tracks.size();
+    for (size_t i = 0; i < size ; i++) {
+        sp<Track> t = tracks[i];
+        int name = getTrackName_l();
+
+        if (name < 0) return;
+
+        t->mName = name;
+        t->mThread = this;
+        mTracks.add(t);
+
+        int j = activeTracks.indexOf(t);
+        if (j >= 0) {
+            mActiveTracks.add(t);
         }
     }
 }
 
-// getTrackName_l() must be called with AudioFlinger::mLock held
+// getTrackName_l() must be called with ThreadBase::mLock held
 int AudioFlinger::MixerThread::getTrackName_l()
 {
     return mAudioMixer->getTrackName();
 }
 
-// deleteTrackName_l() must be called with AudioFlinger::mLock held
+// deleteTrackName_l() must be called with ThreadBase::mLock held
 void AudioFlinger::MixerThread::deleteTrackName_l(int name)
 {
     mAudioMixer->deleteTrackName(name);
 }
 
-size_t AudioFlinger::MixerThread::getOutputFrameCount() 
+// checkForNewParameters_l() must be called with ThreadBase::mLock held
+bool AudioFlinger::MixerThread::checkForNewParameters_l()
 {
-    return mOutput->bufferSize() / mOutput->channelCount() / sizeof(int16_t);
+    bool reconfig = false;
+
+    if (mNewParameters != "") {
+        status_t status = NO_ERROR;
+        AudioParameter param = AudioParameter(mNewParameters);
+        int value;
+        if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
+            if (value != AudioSystem::PCM_16_BIT) {
+                status = BAD_VALUE;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
+            if (value != AudioSystem::CHANNEL_OUT_STEREO) {
+                status = BAD_VALUE;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+            // do not accept frame count changes if tracks are open as the track buffer
+            // size depends on frame count and correct behavior would not be garantied
+            // if frame count is changed after track creation
+            if (!mTracks.isEmpty()) {
+                status = INVALID_OPERATION;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (status == NO_ERROR) {
+            status = mOutput->setParameters(mNewParameters);
+            if (!mStandby && status == INVALID_OPERATION) {
+               mOutput->standby();
+               mStandby = true;
+               mBytesWritten = 0;
+               status = mOutput->setParameters(mNewParameters);
+            }
+            if (status == NO_ERROR && reconfig) {
+                delete mAudioMixer;
+                readOutputParameters();
+                mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
+                for (size_t i = 0; i < mTracks.size() ; i++) {
+                    int name = getTrackName_l();
+                    if (name < 0) break;
+                    mTracks[i]->mName = name;
+                }
+                sendConfigEvent(AudioSystem::OUTPUT_CONFIG_CHANGED);
+            }
+        }
+        mParamStatus = status;
+        mNewParameters = "";
+        mParamCond.signal();
+    }
+    return reconfig;
+}
+
+status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    PlaybackThread::dumpInternals(fd, args);
+
+    snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
+    :   PlaybackThread(audioFlinger, output),
+    mLeftVolume (1.0), mRightVolume(1.0)
+{
+    mType = PlaybackThread::DIRECT;
+}
+
+AudioFlinger::DirectOutputThread::~DirectOutputThread()
+{
+}
+
+
+bool AudioFlinger::DirectOutputThread::threadLoop()
+{
+    unsigned long sleepTime = kBufferRecoveryInUsecs;
+    sp<Track> trackToRemove;
+    sp<Track> activeTrack;
+    nsecs_t standbyTime = systemTime();
+    int8_t *curBuf;
+    size_t mixBufferSize = mFrameCount*mFrameSize;
+
+    while (!exitPending())
+    {
+        processConfigEvents();
+
+        { // scope for the mLock
+
+            Mutex::Autolock _l(mLock);
+
+            if (checkForNewParameters_l()) {
+                mixBufferSize = mFrameCount*mFrameSize;
+            }
+
+            // put audio hardware into standby after short delay
+            if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
+                        mSuspended) {
+                // wait until we have something to do...
+                if (!mStandby) {
+                    LOGV("Audio hardware entering standby, mixer %p\n", this);
+                    mOutput->standby();
+                    mStandby = true;
+                    mBytesWritten = 0;
+                }
+
+                if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+
+                    if (exitPending()) break;
+
+                    LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
+                    mWaitWorkCV.wait(mLock);
+                    LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
+
+                    if (mMasterMute == false) {
+                        char value[PROPERTY_VALUE_MAX];
+                        property_get("ro.audio.silent", value, "0");
+                        if (atoi(value)) {
+                            LOGD("Silence is golden");
+                            setMasterMute(true);
+                        }
+                    }
+
+                    standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    continue;
+                }
+            }
+
+            // find out which tracks need to be processed
+            if (mActiveTracks.size() != 0) {
+                sp<Track> t = mActiveTracks[0].promote();
+                if (t == 0) continue;
+
+                Track* const track = t.get();
+                audio_track_cblk_t* cblk = track->cblk();
+
+                // The first time a track is added we wait
+                // for all its buffers to be filled before processing it
+                if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
+                        !track->isPaused())
+                {
+                    //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
+
+                    // compute volume for this track
+                    float left, right;
+                    if (track->isMuted() || mMasterMute || track->isPausing() ||
+                        mStreamTypes[track->type()].mute) {
+                        left = right = 0;
+                        if (track->isPausing()) {
+                            track->setPaused();
+                        }
+                    } else {
+                        float typeVolume = mStreamTypes[track->type()].volume;
+                        float v = mMasterVolume * typeVolume;
+                        float v_clamped = v * cblk->volume[0];
+                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                        left = v_clamped/MAX_GAIN;
+                        v_clamped = v * cblk->volume[1];
+                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                        right = v_clamped/MAX_GAIN;
+                    }
+
+                    if (left != mLeftVolume || right != mRightVolume) {
+                        mOutput->setVolume(left, right);
+                        left = mLeftVolume;
+                        right = mRightVolume;
+                    }
+
+                    if (track->mFillingUpStatus == Track::FS_FILLED) {
+                        track->mFillingUpStatus = Track::FS_ACTIVE;
+                        if (track->mState == TrackBase::RESUMING) {
+                            track->mState = TrackBase::ACTIVE;
+                        }
+                    }
+
+                    // reset retry count
+                    track->mRetryCount = kMaxTrackRetries;
+                    activeTrack = t;
+                } else {
+                    //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
+                    if (track->isStopped()) {
+                        track->reset();
+                    }
+                    if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+                        // We have consumed all the buffers of this track.
+                        // Remove it from the list of active tracks.
+                        trackToRemove = track;
+                    } else {
+                        // No buffers for this track. Give it a few chances to
+                        // fill a buffer, then remove it from active list.
+                        if (--(track->mRetryCount) <= 0) {
+                            LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
+                            trackToRemove = track;
+                        }
+
+                        // For tracks using static shared memry buffer, make sure that we have
+                        // written enough data to audio hardware before disabling the track
+                        // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
+                        // don't care about code removing track from active list above.
+                        if ((track->mSharedBuffer != 0) && (mBytesWritten < mMinBytesToWrite)) {
+                            activeTrack = t;
+                        }
+                     }
+                }
+            }
+
+            // remove all the tracks that need to be...
+            if (UNLIKELY(trackToRemove != 0)) {
+                mActiveTracks.remove(trackToRemove);
+                if (trackToRemove->isTerminated()) {
+                    mTracks.remove(trackToRemove);
+                    deleteTrackName_l(trackToRemove->mName);
+                }
+            }
+       }
+
+        if (activeTrack != 0) {
+            AudioBufferProvider::Buffer buffer;
+            size_t frameCount = mFrameCount;
+            curBuf = (int8_t *)mMixBuffer;
+            // output audio to hardware
+            mLastWriteTime = systemTime();
+            mInWrite = true;
+            while(frameCount) {
+                buffer.frameCount = frameCount;
+                activeTrack->getNextBuffer(&buffer);
+                if (UNLIKELY(buffer.raw == 0)) {
+                    memset(curBuf, 0, frameCount * mFrameSize);
+                    break;
+                }
+                memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
+                frameCount -= buffer.frameCount;
+                curBuf += buffer.frameCount * mFrameSize;
+                activeTrack->releaseBuffer(&buffer);
+            }
+            if (mSuspended) {
+                usleep(kMaxBufferRecoveryInUsecs);
+            } else {
+                int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
+                if (bytesWritten) mBytesWritten += bytesWritten;
+                mNumWrites++;
+                mInWrite = false;
+                mStandby = false;
+                nsecs_t temp = systemTime();
+                standbyTime = temp + kStandbyTimeInNsecs;
+                sleepTime = kBufferRecoveryInUsecs;
+            }
+        } else {
+            // There was nothing to mix this round, which means all
+            // active tracks were late. Sleep a little bit to give
+            // them another chance. If we're too late, the audio
+            // hardware will zero-fill for us.
+            //LOGV("no buffers - usleep(%lu)", sleepTime);
+            usleep(sleepTime);
+            if (sleepTime < kMaxBufferRecoveryInUsecs) {
+                sleepTime += kBufferRecoveryInUsecs;
+            }
+        }
+
+        // finally let go of removed track, without the lock held
+        // since we can't guarantee the destructors won't acquire that
+        // same lock.
+        trackToRemove.clear();
+        activeTrack.clear();
+    }
+
+    if (!mStandby) {
+        mOutput->standby();
+    }
+    sendConfigEvent(AudioSystem::OUTPUT_CLOSED);
+    processConfigEvents();
+
+    LOGV("DirectOutputThread %p exiting", this);
+    return false;
+}
+
+// getTrackName_l() must be called with ThreadBase::mLock held
+int AudioFlinger::DirectOutputThread::getTrackName_l()
+{
+    return 0;
+}
+
+// deleteTrackName_l() must be called with ThreadBase::mLock held
+void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
+{
+}
+
+// checkForNewParameters_l() must be called with ThreadBase::mLock held
+bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
+{
+    bool reconfig = false;
+
+    if (mNewParameters != "") {
+        status_t status = NO_ERROR;
+        AudioParameter param = AudioParameter(mNewParameters);
+        int value;
+        if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+            // do not accept frame count changes if tracks are open as the track buffer
+            // size depends on frame count and correct behavior would not be garantied
+            // if frame count is changed after track creation
+            if (!mTracks.isEmpty()) {
+                status = INVALID_OPERATION;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (status == NO_ERROR) {
+            status = mOutput->setParameters(mNewParameters);
+            if (!mStandby && status == INVALID_OPERATION) {
+               mOutput->standby();
+               mStandby = true;
+               mBytesWritten = 0;
+               status = mOutput->setParameters(mNewParameters);
+            }
+            if (status == NO_ERROR && reconfig) {
+                readOutputParameters();
+                sendConfigEvent(AudioSystem::OUTPUT_CONFIG_CHANGED);
+            }
+        }
+        mParamStatus = status;
+        mNewParameters = "";
+        mParamCond.signal();
+    }
+    return reconfig;
 }
 
 // ----------------------------------------------------------------------------
 
+AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread)
+    :   MixerThread(audioFlinger, mainThread->getOutput())
+{
+    mType = PlaybackThread::DUPLICATING;
+    addOutputTrack(mainThread);
+}
+
+AudioFlinger::DuplicatingThread::~DuplicatingThread()
+{
+    mOutputTracks.clear();
+}
+
+bool AudioFlinger::DuplicatingThread::threadLoop()
+{
+    unsigned long sleepTime = kBufferRecoveryInUsecs;
+    int16_t* curBuf = mMixBuffer;
+    Vector< sp<Track> > tracksToRemove;
+    size_t enabledTracks = 0;
+    nsecs_t standbyTime = systemTime();
+    size_t mixBufferSize = mFrameCount*mFrameSize;
+    SortedVector< sp<OutputTrack> > outputTracks;
+
+    while (!exitPending())
+    {
+        processConfigEvents();
+
+        enabledTracks = 0;
+        { // scope for the mLock
+
+            Mutex::Autolock _l(mLock);
+
+            if (checkForNewParameters_l()) {
+                mixBufferSize = mFrameCount*mFrameSize;
+            }
+
+            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
+
+            for (size_t i = 0; i < mOutputTracks.size(); i++) {
+                outputTracks.add(mOutputTracks[i]);
+            }
+
+            // put audio hardware into standby after short delay
+            if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
+                         mSuspended) {
+                if (!mStandby) {
+                    for (size_t i = 0; i < outputTracks.size(); i++) {
+                        mLock.unlock();
+                        outputTracks[i]->stop();
+                        mLock.lock();
+                    }
+                    mStandby = true;
+                    mBytesWritten = 0;
+                }
+
+                if (!activeTracks.size() && mConfigEvents.isEmpty()) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+                    outputTracks.clear();
+
+                    if (exitPending()) break;
+
+                    LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
+                    mWaitWorkCV.wait(mLock);
+                    LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
+                    if (mMasterMute == false) {
+                        char value[PROPERTY_VALUE_MAX];
+                        property_get("ro.audio.silent", value, "0");
+                        if (atoi(value)) {
+                            LOGD("Silence is golden");
+                            setMasterMute(true);
+                        }
+                    }
+
+                    standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = kBufferRecoveryInUsecs;
+                    continue;
+                }
+            }
+
+            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
+       }
+
+        bool mustSleep = true;
+        if (LIKELY(enabledTracks)) {
+            // mix buffers...
+            mAudioMixer->process(curBuf);
+            if (!mSuspended) {
+                for (size_t i = 0; i < outputTracks.size(); i++) {
+                    outputTracks[i]->write(curBuf, mFrameCount);
+                }
+                mStandby = false;
+                mustSleep = false;
+                mBytesWritten += mixBufferSize;
+            }
+        } else {
+            // flush remaining overflow buffers in output tracks
+            for (size_t i = 0; i < outputTracks.size(); i++) {
+                if (outputTracks[i]->isActive()) {
+                    outputTracks[i]->write(curBuf, 0);
+                    standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    mustSleep = false;
+                }
+            }
+        }
+        if (mustSleep) {
+//            LOGV("threadLoop() sleeping %d", sleepTime);
+            usleep(sleepTime);
+            if (sleepTime < kMaxBufferRecoveryInUsecs) {
+                sleepTime += kBufferRecoveryInUsecs;
+            }
+        } else {
+            sleepTime = kBufferRecoveryInUsecs;
+        }
+
+        // finally let go of all our tracks, without the lock held
+        // since we can't guarantee the destructors won't acquire that
+        // same lock.
+        tracksToRemove.clear();
+        outputTracks.clear();
+    }
+
+    if (!mStandby) {
+        for (size_t i = 0; i < outputTracks.size(); i++) {
+            mLock.unlock();
+            outputTracks[i]->stop();
+            mLock.lock();
+        }
+    }
+
+    sendConfigEvent(AudioSystem::OUTPUT_CLOSED);
+    processConfigEvents();
+
+    return false;
+}
+
+void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
+{
+    int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
+    OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
+                                            mSampleRate,
+                                            mFormat,
+                                            mChannelCount,
+                                            frameCount);
+    thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
+    mOutputTracks.add(outputTrack);
+    LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
+}
+
+void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
+{
+    Mutex::Autolock _l(mLock);
+    for (size_t i = 0; i < mOutputTracks.size(); i++) {
+        if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
+            mOutputTracks.removeAt(i);
+            return;
+        }
+    }
+    LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
+}
+
+
+// ----------------------------------------------------------------------------
+
 // TrackBase constructor must be called with AudioFlinger::mLock held
-AudioFlinger::MixerThread::TrackBase::TrackBase(
-            const sp<MixerThread>& mixerThread,
+AudioFlinger::ThreadBase::TrackBase::TrackBase(
+            const wp<ThreadBase>& thread,
             const sp<Client>& client,
             uint32_t sampleRate,
             int format,
@@ -1574,7 +1950,7 @@
             uint32_t flags,
             const sp<IMemory>& sharedBuffer)
     :   RefBase(),
-        mMixerThread(mixerThread),
+        mThread(thread),
         mClient(client),
         mFrameCount(0),
         mState(IDLE),
@@ -1582,13 +1958,6 @@
         mFormat(format),
         mFlags(flags & ~SYSTEM_FLAGS_MASK)
 {
-    mName = mixerThread->getTrackName_l();
-    LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
-    if (mName < 0) {
-        LOGE("no more track names availlable");
-        return;
-    }
-
     LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
 
     // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
@@ -1642,16 +2011,19 @@
    }
 }
 
-AudioFlinger::MixerThread::TrackBase::~TrackBase()
+AudioFlinger::PlaybackThread::TrackBase::~TrackBase()
 {
     if (mCblk) {
-        mCblk->~audio_track_cblk_t();   // destroy our shared-structure.        
+        mCblk->~audio_track_cblk_t();   // destroy our shared-structure.
+        if (mClient == NULL) {
+            delete mCblk;
+        }
     }
     mCblkMemory.clear();            // and free the shared memory
     mClient.clear();
 }
 
-void AudioFlinger::MixerThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void AudioFlinger::PlaybackThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
 {
     buffer->raw = 0;
     mFrameCount = buffer->frameCount;
@@ -1659,7 +2031,7 @@
     buffer->frameCount = 0;
 }
 
-bool AudioFlinger::MixerThread::TrackBase::step() {
+bool AudioFlinger::PlaybackThread::TrackBase::step() {
     bool result;
     audio_track_cblk_t* cblk = this->cblk();
 
@@ -1671,7 +2043,7 @@
     return result;
 }
 
-void AudioFlinger::MixerThread::TrackBase::reset() {
+void AudioFlinger::PlaybackThread::TrackBase::reset() {
     audio_track_cblk_t* cblk = this->cblk();
 
     cblk->user = 0;
@@ -1682,27 +2054,27 @@
     LOGV("TrackBase::reset");
 }
 
-sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const
+sp<IMemory> AudioFlinger::PlaybackThread::TrackBase::getCblk() const
 {
     return mCblkMemory;
 }
 
-int AudioFlinger::MixerThread::TrackBase::sampleRate() const {
+int AudioFlinger::PlaybackThread::TrackBase::sampleRate() const {
     return (int)mCblk->sampleRate;
 }
 
-int AudioFlinger::MixerThread::TrackBase::channelCount() const {
+int AudioFlinger::PlaybackThread::TrackBase::channelCount() const {
     return (int)mCblk->channels;
 }
 
-void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
+void* AudioFlinger::PlaybackThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
     audio_track_cblk_t* cblk = this->cblk();
-    int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
-    int16_t *bufferEnd = bufferStart + frames * cblk->channels;
+    int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
+    int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
 
     // Check validity of returned pointer in case the track control block would have been corrupted.
-    if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd || 
-        (cblk->channels == 2 && ((unsigned long)bufferStart & 3))) {
+    if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
+        ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
         LOGE("TrackBase::getBuffer buffer out of range:\n    start: %p, end %p , mBuffer %p mBufferEnd %p\n    \
                 server %d, serverBase %d, user %d, userBase %d, channels %d",
                 bufferStart, bufferEnd, mBuffer, mBufferEnd,
@@ -1715,9 +2087,9 @@
 
 // ----------------------------------------------------------------------------
 
-// Track constructor must be called with AudioFlinger::mLock held
-AudioFlinger::MixerThread::Track::Track(
-            const sp<MixerThread>& mixerThread,
+// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
+AudioFlinger::PlaybackThread::Track::Track(
+            const wp<ThreadBase>& thread,
             const sp<Client>& client,
             int streamType,
             uint32_t sampleRate,
@@ -1725,40 +2097,58 @@
             int channelCount,
             int frameCount,
             const sp<IMemory>& sharedBuffer)
-    :   TrackBase(mixerThread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer)
+    :   TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer),
+    mMute(false), mSharedBuffer(sharedBuffer), mName(-1)
 {
+    sp<ThreadBase> baseThread = thread.promote();
+    if (baseThread != 0) {
+        PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
+        mName = playbackThread->getTrackName_l();
+    }
+    LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+    if (mName < 0) {
+        LOGE("no more track names available");
+    }
     mVolume[0] = 1.0f;
     mVolume[1] = 1.0f;
-    mMute = false;
-    mSharedBuffer = sharedBuffer;
     mStreamType = streamType;
+    // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
+    // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
+    mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
 }
 
-AudioFlinger::MixerThread::Track::~Track()
+AudioFlinger::PlaybackThread::Track::~Track()
 {
-    wp<Track> weak(this); // never create a strong ref from the dtor
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    mState = TERMINATED;
-}
-
-void AudioFlinger::MixerThread::Track::destroy()
-{
-    // NOTE: destroyTrack_l() can remove a strong reference to this Track 
-    // by removing it from mTracks vector, so there is a risk that this Tracks's
-    // desctructor is called. As the destructor needs to lock AudioFlinger::mLock,
-    // we must acquire a strong reference on this Track before locking AudioFlinger::mLock
-    // here so that the destructor is called only when exiting this function.
-    // On the other hand, as long as Track::destroy() is only called by 
-    // TrackHandle destructor, the TrackHandle still holds a strong ref on 
-    // this Track with its member mTrack.
-    sp<Track> keep(this);
-    { // scope for AudioFlinger::mLock
-        Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-        mMixerThread->destroyTrack_l(this);
+    LOGV("PlaybackThread::Track destructor");
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        mState = TERMINATED;
     }
 }
 
-void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size)
+void AudioFlinger::PlaybackThread::Track::destroy()
+{
+    // NOTE: destroyTrack_l() can remove a strong reference to this Track
+    // by removing it from mTracks vector, so there is a risk that this Tracks's
+    // desctructor is called. As the destructor needs to lock mLock,
+    // we must acquire a strong reference on this Track before locking mLock
+    // here so that the destructor is called only when exiting this function.
+    // On the other hand, as long as Track::destroy() is only called by
+    // TrackHandle destructor, the TrackHandle still holds a strong ref on
+    // this Track with its member mTrack.
+    sp<Track> keep(this);
+    { // scope for mLock
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            Mutex::Autolock _l(thread->mLock);
+            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            playbackThread->destroyTrack_l(this);
+        }
+    }
+}
+
+void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
 {
     snprintf(buffer, size, "  %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
             mName - AudioMixer::TRACK0,
@@ -1777,7 +2167,7 @@
             mCblk->user);
 }
 
-status_t AudioFlinger::MixerThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
 {
      audio_track_cblk_t* cblk = this->cblk();
      uint32_t framesReady;
@@ -1814,76 +2204,90 @@
 getNextBuffer_exit:
      buffer->raw = 0;
      buffer->frameCount = 0;
+     LOGV("getNextBuffer() no more data");
      return NOT_ENOUGH_DATA;
 }
 
-bool AudioFlinger::MixerThread::Track::isReady() const {
+bool AudioFlinger::PlaybackThread::Track::isReady() const {
     if (mFillingUpStatus != FS_FILLING) return true;
 
     if (mCblk->framesReady() >= mCblk->frameCount ||
         mCblk->forceReady) {
         mFillingUpStatus = FS_FILLED;
         mCblk->forceReady = 0;
-        LOGV("Track::isReady() track %d for output %d", mName, mMixerThread->mOutputType);
         return true;
     }
     return false;
 }
 
-status_t AudioFlinger::MixerThread::Track::start()
+status_t AudioFlinger::PlaybackThread::Track::start()
 {
-    LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    mMixerThread->addTrack_l(this);
+    LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        playbackThread->addTrack_l(this);
+    }
     return NO_ERROR;
 }
 
-void AudioFlinger::MixerThread::Track::stop()
+void AudioFlinger::PlaybackThread::Track::stop()
 {
-    LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    if (mState > STOPPED) {
-        mState = STOPPED;
-        // If the track is not active (PAUSED and buffers full), flush buffers
-        if (mMixerThread->mActiveTracks.indexOf(this) < 0) {
-            reset();
+    LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        if (mState > STOPPED) {
+            mState = STOPPED;
+            // If the track is not active (PAUSED and buffers full), flush buffers
+            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+                reset();
+            }
+            LOGV("(> STOPPED) => STOPPED (%d)", mName);
         }
-        LOGV("(> STOPPED) => STOPPED (%d)", mName);
     }
 }
 
-void AudioFlinger::MixerThread::Track::pause()
+void AudioFlinger::PlaybackThread::Track::pause()
 {
     LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    if (mState == ACTIVE || mState == RESUMING) {
-        mState = PAUSING;
-        LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        if (mState == ACTIVE || mState == RESUMING) {
+            mState = PAUSING;
+            LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
+        }
     }
 }
 
-void AudioFlinger::MixerThread::Track::flush()
+void AudioFlinger::PlaybackThread::Track::flush()
 {
     LOGV("flush(%d)", mName);
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
-        return;
-    }
-    // No point remaining in PAUSED state after a flush => go to
-    // STOPPED state
-    mState = STOPPED;
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
+            return;
+        }
+        // No point remaining in PAUSED state after a flush => go to
+        // STOPPED state
+        mState = STOPPED;
 
-    mCblk->lock.lock();
-    // NOTE: reset() will reset cblk->user and cblk->server with
-    // the risk that at the same time, the AudioMixer is trying to read
-    // data. In this case, getNextBuffer() would return a NULL pointer
-    // as audio buffer => the AudioMixer code MUST always test that pointer
-    // returned by getNextBuffer() is not NULL!
-    reset();
-    mCblk->lock.unlock();
+        mCblk->lock.lock();
+        // NOTE: reset() will reset cblk->user and cblk->server with
+        // the risk that at the same time, the AudioMixer is trying to read
+        // data. In this case, getNextBuffer() would return a NULL pointer
+        // as audio buffer => the AudioMixer code MUST always test that pointer
+        // returned by getNextBuffer() is not NULL!
+        reset();
+        mCblk->lock.unlock();
+    }
 }
 
-void AudioFlinger::MixerThread::Track::reset()
+void AudioFlinger::PlaybackThread::Track::reset()
 {
     // Do not reset twice to avoid discarding data written just after a flush and before
     // the audioflinger thread detects the track is stopped.
@@ -1893,17 +2297,17 @@
         // written to buffer
         mCblk->flowControlFlag = 1;
         mCblk->forceReady = 0;
-        mFillingUpStatus = FS_FILLING;        
+        mFillingUpStatus = FS_FILLING;
         mResetDone = true;
     }
 }
 
-void AudioFlinger::MixerThread::Track::mute(bool muted)
+void AudioFlinger::PlaybackThread::Track::mute(bool muted)
 {
     mMute = muted;
 }
 
-void AudioFlinger::MixerThread::Track::setVolume(float left, float right)
+void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
 {
     mVolume[0] = left;
     mVolume[1] = right;
@@ -1912,28 +2316,33 @@
 // ----------------------------------------------------------------------------
 
 // RecordTrack constructor must be called with AudioFlinger::mLock held
-AudioFlinger::MixerThread::RecordTrack::RecordTrack(
-            const sp<MixerThread>& mixerThread,
+AudioFlinger::RecordThread::RecordTrack::RecordTrack(
+            const wp<ThreadBase>& thread,
             const sp<Client>& client,
-            int inputSource,
             uint32_t sampleRate,
             int format,
             int channelCount,
             int frameCount,
             uint32_t flags)
-    :   TrackBase(mixerThread, client, sampleRate, format,
+    :   TrackBase(thread, client, sampleRate, format,
                   channelCount, frameCount, flags, 0),
-        mOverflow(false), mInputSource(inputSource)
+        mOverflow(false)
+{
+   LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
+   if (format == AudioSystem::PCM_16_BIT) {
+       mCblk->frameSize = channelCount * sizeof(int16_t);
+   } else if (format == AudioSystem::PCM_8_BIT) {
+       mCblk->frameSize = channelCount * sizeof(int8_t);
+   } else {
+       mCblk->frameSize = sizeof(int8_t);
+   }
+}
+
+AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
 {
 }
 
-AudioFlinger::MixerThread::RecordTrack::~RecordTrack()
-{
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    mMixerThread->deleteTrackName_l(mName);
-}
-
-status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
 {
     audio_track_cblk_t* cblk = this->cblk();
     uint32_t framesAvail;
@@ -1972,180 +2381,231 @@
     return NOT_ENOUGH_DATA;
 }
 
-status_t AudioFlinger::MixerThread::RecordTrack::start()
+status_t AudioFlinger::RecordThread::RecordTrack::start()
 {
-    return mMixerThread->mAudioFlinger->startRecord(this);
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        RecordThread *recordThread = (RecordThread *)thread.get();
+        return recordThread->start(this);
+    }
+    return NO_INIT;
 }
 
-void AudioFlinger::MixerThread::RecordTrack::stop()
+void AudioFlinger::RecordThread::RecordTrack::stop()
 {
-    mMixerThread->mAudioFlinger->stopRecord(this);
-    TrackBase::reset();
-    // Force overerrun condition to avoid false overrun callback until first data is
-    // read from buffer
-    mCblk->flowControlFlag = 1;
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        RecordThread *recordThread = (RecordThread *)thread.get();
+        recordThread->stop(this);
+        TrackBase::reset();
+        // Force overerrun condition to avoid false overrun callback until first data is
+        // read from buffer
+        mCblk->flowControlFlag = 1;
+    }
 }
 
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::MixerThread::OutputTrack::OutputTrack(
-            const sp<MixerThread>& mixerThread,
+AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
+            const wp<ThreadBase>& thread,
             uint32_t sampleRate,
             int format,
             int channelCount,
             int frameCount)
-    :   Track(mixerThread, NULL, AudioSystem::SYSTEM, sampleRate, format, channelCount, frameCount, NULL),
-    mOutputMixerThread(mixerThread)
+    :   Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL),
+    mActive(false)
 {
-                
+
+    PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
     mCblk->out = 1;
     mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
     mCblk->volume[0] = mCblk->volume[1] = 0x1000;
     mOutBuffer.frameCount = 0;
-    mCblk->bufferTimeoutMs = 10;
-    
-    LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p", 
-            mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd);
-    
+    mWaitTimeMs = (playbackThread->frameCount() * 2 * 1000) / playbackThread->sampleRate();
+
+    LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p mWaitTimeMs %d",
+            mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd, mWaitTimeMs);
+
 }
 
-AudioFlinger::MixerThread::OutputTrack::~OutputTrack()
+AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
 {
     stop();
 }
 
-status_t AudioFlinger::MixerThread::OutputTrack::start()
+status_t AudioFlinger::PlaybackThread::OutputTrack::start()
 {
     status_t status = Track::start();
-    
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    mActive = true;
     mRetryCount = 127;
     return status;
 }
 
-void AudioFlinger::MixerThread::OutputTrack::stop()
+void AudioFlinger::PlaybackThread::OutputTrack::stop()
 {
     Track::stop();
     clearBufferQueue();
     mOutBuffer.frameCount = 0;
+    mActive = false;
 }
 
-void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frames)
+bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
 {
     Buffer *pInBuffer;
     Buffer inBuffer;
     uint32_t channels = mCblk->channels;
-        
+    bool outputBufferFull = false;
     inBuffer.frameCount = frames;
     inBuffer.i16 = data;
-    
-    if (mCblk->user == 0) {
-        mOutputMixerThread->mAudioFlinger->mLock.lock();
-        bool isMusicActive = mOutputMixerThread->isMusicActive_l();
-        mOutputMixerThread->mAudioFlinger->mLock.unlock();
-        if (isMusicActive) {
-            mCblk->forceReady = 1;
-            LOGV("OutputTrack::start() force ready");
-        } else if (mCblk->frameCount > frames){
-            if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
-                uint32_t startFrames = (mCblk->frameCount - frames);
-                LOGV("OutputTrack::start() write %d frames", startFrames);
-                pInBuffer = new Buffer;
-                pInBuffer->mBuffer = new int16_t[startFrames * channels];
-                pInBuffer->frameCount = startFrames;
-                pInBuffer->i16 = pInBuffer->mBuffer;
-                memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
-                mBufferQueue.add(pInBuffer);                
-            } else {
-                LOGW ("OutputTrack::write() no more buffers");
+
+    uint32_t waitTimeLeftMs = mWaitTimeMs;
+
+    if (!mActive) {
+        start();
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            MixerThread *mixerThread = (MixerThread *)thread.get();
+            if (mCblk->frameCount > frames){
+                if (mBufferQueue.size() < kMaxOverFlowBuffers) {
+                    uint32_t startFrames = (mCblk->frameCount - frames);
+                    pInBuffer = new Buffer;
+                    pInBuffer->mBuffer = new int16_t[startFrames * channels];
+                    pInBuffer->frameCount = startFrames;
+                    pInBuffer->i16 = pInBuffer->mBuffer;
+                    memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
+                    mBufferQueue.add(pInBuffer);
+                } else {
+                    LOGW ("OutputTrack::write() %p no more buffers in queue", this);
+                }
             }
-        }        
+        }
     }
 
-    while (1) { 
+    while (waitTimeLeftMs) {
         // First write pending buffers, then new data
         if (mBufferQueue.size()) {
             pInBuffer = mBufferQueue.itemAt(0);
         } else {
             pInBuffer = &inBuffer;
         }
- 
+
         if (pInBuffer->frameCount == 0) {
             break;
         }
-        
+
         if (mOutBuffer.frameCount == 0) {
             mOutBuffer.frameCount = pInBuffer->frameCount;
-            if (obtainBuffer(&mOutBuffer) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
+            nsecs_t startTime = systemTime();
+            if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
+                LOGV ("OutputTrack::write() %p no more output buffers", this);
+                outputBufferFull = true;
                 break;
             }
+            uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
+//            LOGV("OutputTrack::write() waitTimeMs %d waitTimeLeftMs %d", waitTimeMs, waitTimeLeftMs)
+            if (waitTimeLeftMs >= waitTimeMs) {
+                waitTimeLeftMs -= waitTimeMs;
+            } else {
+                waitTimeLeftMs = 0;
+            }
         }
-            
+
         uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
         memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t));
         mCblk->stepUser(outFrames);
         pInBuffer->frameCount -= outFrames;
         pInBuffer->i16 += outFrames * channels;
         mOutBuffer.frameCount -= outFrames;
-        mOutBuffer.i16 += outFrames * channels;            
-        
+        mOutBuffer.i16 += outFrames * channels;
+
         if (pInBuffer->frameCount == 0) {
             if (mBufferQueue.size()) {
                 mBufferQueue.removeAt(0);
                 delete [] pInBuffer->mBuffer;
                 delete pInBuffer;
+                LOGV("OutputTrack::write() %p released overflow buffer %d", this, mBufferQueue.size());
             } else {
                 break;
             }
         }
     }
- 
+
     // If we could not write all frames, allocate a buffer and queue it for next time.
     if (inBuffer.frameCount) {
-        if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
+        if (mBufferQueue.size() < kMaxOverFlowBuffers) {
             pInBuffer = new Buffer;
             pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
             pInBuffer->frameCount = inBuffer.frameCount;
             pInBuffer->i16 = pInBuffer->mBuffer;
             memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
             mBufferQueue.add(pInBuffer);
+            LOGV("OutputTrack::write() %p adding overflow buffer %d", this, mBufferQueue.size());
         } else {
-            LOGW("OutputTrack::write() no more buffers");
+            LOGW("OutputTrack::write() %p no more overflow buffers", this);
         }
     }
-    
+
     // Calling write() with a 0 length buffer, means that no more data will be written:
-    // If no more buffers are pending, fill output track buffer to make sure it is started 
+    // If no more buffers are pending, fill output track buffer to make sure it is started
     // by output mixer.
-    if (frames == 0 && mBufferQueue.size() == 0 && mCblk->user < mCblk->frameCount) {
-        frames = mCblk->frameCount - mCblk->user;
-        pInBuffer = new Buffer;
-        pInBuffer->mBuffer = new int16_t[frames * channels];
-        pInBuffer->frameCount = frames;
-        pInBuffer->i16 = pInBuffer->mBuffer;
-        memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
-        mBufferQueue.add(pInBuffer);
+    if (frames == 0 && mBufferQueue.size() == 0) {
+        if (mCblk->user < mCblk->frameCount) {
+            frames = mCblk->frameCount - mCblk->user;
+            pInBuffer = new Buffer;
+            pInBuffer->mBuffer = new int16_t[frames * channels];
+            pInBuffer->frameCount = frames;
+            pInBuffer->i16 = pInBuffer->mBuffer;
+            memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
+            mBufferQueue.add(pInBuffer);
+        } else {
+            stop();
+        }
     }
 
+    return outputBufferFull;
 }
 
-status_t AudioFlinger::MixerThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer)
+status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
 {
     int active;
-    int timeout = 0;
     status_t result;
     audio_track_cblk_t* cblk = mCblk;
     uint32_t framesReq = buffer->frameCount;
 
-    LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
+//    LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
     buffer->frameCount  = 0;
-    
+
     uint32_t framesAvail = cblk->framesAvailable();
 
+
     if (framesAvail == 0) {
-        return AudioTrack::NO_MORE_BUFFERS;
+        Mutex::Autolock _l(cblk->lock);
+        goto start_loop_here;
+        while (framesAvail == 0) {
+            active = mActive;
+            if (UNLIKELY(!active)) {
+                LOGV("Not active and NO_MORE_BUFFERS");
+                return AudioTrack::NO_MORE_BUFFERS;
+            }
+            result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
+            if (result != NO_ERROR) {
+                return AudioTrack::NO_MORE_BUFFERS;
+            }
+            // read the server count again
+        start_loop_here:
+            framesAvail = cblk->framesAvailable_l();
+        }
     }
 
+//    if (framesAvail < framesReq) {
+//        return AudioTrack::NO_MORE_BUFFERS;
+//    }
+
     if (framesReq > framesAvail) {
         framesReq = framesAvail;
     }
@@ -2163,11 +2623,11 @@
 }
 
 
-void AudioFlinger::MixerThread::OutputTrack::clearBufferQueue()
+void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
 {
     size_t size = mBufferQueue.size();
     Buffer *pBuffer;
-    
+
     for (size_t i = 0; i < size; i++) {
         pBuffer = mBufferQueue.itemAt(i);
         delete [] pBuffer->mBuffer;
@@ -2199,7 +2659,7 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::MixerThread::Track>& track)
+AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
     : BnAudioTrack(),
       mTrack(track)
 {
@@ -2251,7 +2711,7 @@
 
 sp<IAudioRecord> AudioFlinger::openRecord(
         pid_t pid,
-        int inputSource,
+        void *input,
         uint32_t sampleRate,
         int format,
         int channelCount,
@@ -2259,14 +2719,13 @@
         uint32_t flags,
         status_t *status)
 {
-    sp<MixerThread::RecordTrack> recordTrack;
+    sp<RecordThread::RecordTrack> recordTrack;
     sp<RecordHandle> recordHandle;
     sp<Client> client;
     wp<Client> wclient;
-    AudioStreamIn* input = 0;
-    int inFrameCount;
-    size_t inputBufferSize;
     status_t lStatus;
+    RecordThread *thread;
+    size_t inFrameCount;
 
     // check calling permissions
     if (!recordingAllowed()) {
@@ -2274,30 +2733,15 @@
         goto Exit;
     }
 
-    if (uint32_t(inputSource) >= AudioRecord::NUM_INPUT_SOURCES) {
-        LOGE("invalid stream type");
-        lStatus = BAD_VALUE;
-        goto Exit;
-    }
-
-    if (mAudioRecordThread == 0) {
-        LOGE("Audio record thread not started");
-        lStatus = NO_INIT;
-        goto Exit;
-    }
-
-
-    // Check that audio input stream accepts requested audio parameters 
-    inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
-    if (inputBufferSize == 0) {
-        lStatus = BAD_VALUE;
-        LOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d",  sampleRate, format, channelCount);
-        goto Exit;
-    }
-
     // add client to list
     { // scope for mLock
         Mutex::Autolock _l(mLock);
+        thread = checkRecordThread_l(input);
+        if (thread == NULL) {
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
+
         wclient = mClients.valueFor(pid);
         if (wclient != NULL) {
             client = wclient.promote();
@@ -2306,12 +2750,8 @@
             mClients.add(pid, client);
         }
 
-        // frameCount must be a multiple of input buffer size
-        inFrameCount = inputBufferSize/channelCount/sizeof(short);
-        frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
-    
         // create new record track. The record track uses one track in mHardwareMixerThread by convention.
-        recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, inputSource, sampleRate,
+        recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
                                                    format, channelCount, frameCount, flags);
     }
     if (recordTrack->getCblk() == NULL) {
@@ -2331,22 +2771,9 @@
     return recordHandle;
 }
 
-status_t AudioFlinger::startRecord(MixerThread::RecordTrack* recordTrack) {
-    if (mAudioRecordThread != 0) {
-        return mAudioRecordThread->start(recordTrack);        
-    }
-    return NO_INIT;
-}
-
-void AudioFlinger::stopRecord(MixerThread::RecordTrack* recordTrack) {
-    if (mAudioRecordThread != 0) {
-        mAudioRecordThread->stop(recordTrack);
-    }
-}
-
 // ----------------------------------------------------------------------------
 
-AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::MixerThread::RecordTrack>& recordTrack)
+AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
     : BnAudioRecord(),
     mRecordTrack(recordTrack)
 {
@@ -2378,86 +2805,165 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware,
-            const sp<AudioFlinger>& audioFlinger) :
-    mAudioHardware(audioHardware),
-    mAudioFlinger(audioFlinger),
-    mActive(false)
+AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels) :
+    ThreadBase(audioFlinger),
+    mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
 {
+    mReqChannelCount = AudioSystem::popCount(channels);
+    mReqSampleRate = sampleRate;
+    readInputParameters();
+    sendConfigEvent(AudioSystem::INPUT_OPENED);
 }
 
-AudioFlinger::AudioRecordThread::~AudioRecordThread()
+
+AudioFlinger::RecordThread::~RecordThread()
 {
+    mAudioFlinger->mAudioHardware->closeInputStream(mInput);
+    delete[] mRsmpInBuffer;
+    if (mResampler != 0) {
+        delete mResampler;
+        delete[] mRsmpOutBuffer;
+    }
 }
 
-bool AudioFlinger::AudioRecordThread::threadLoop()
+void AudioFlinger::RecordThread::onFirstRef()
 {
-    LOGV("AudioRecordThread: start record loop");
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "Record Thread %p", this);
+
+    run(buffer, PRIORITY_URGENT_AUDIO);
+}
+bool AudioFlinger::RecordThread::threadLoop()
+{
     AudioBufferProvider::Buffer buffer;
-    int inBufferSize = 0;
-    int inFrameCount = 0;
-    AudioStreamIn* input = 0;
+    sp<RecordTrack> activeTrack;
 
-    mActive = 0;
-    
     // start recording
     while (!exitPending()) {
-        if (!mActive) {
-            mLock.lock();
-            if (!mActive && !exitPending()) {
-                LOGV("AudioRecordThread: loop stopping");
-                if (input) {
-                    delete input;
-                    input = 0;
-                }
-                mRecordTrack.clear();
-                mStopped.signal();
 
+        processConfigEvents();
+
+        { // scope for mLock
+            Mutex::Autolock _l(mLock);
+            checkForNewParameters_l();
+            if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
+                if (!mStandby) {
+                    mInput->standby();
+                    mStandby = true;
+                }
+
+                if (exitPending()) break;
+
+                LOGV("RecordThread: loop stopping");
+                // go to sleep
                 mWaitWorkCV.wait(mLock);
-               
-                LOGV("AudioRecordThread: loop starting");
-                if (mRecordTrack != 0) {
-                    input = mAudioHardware->openInputStream(
-                                    mRecordTrack->inputSource(),
-                                    mRecordTrack->format(), 
-                                    mRecordTrack->channelCount(), 
-                                    mRecordTrack->sampleRate(), 
-                                    &mStartStatus,
-                                    (AudioSystem::audio_in_acoustics)(mRecordTrack->mFlags >> 16));
-                    if (input != 0) {
-                        inBufferSize = input->bufferSize();
-                        inFrameCount = inBufferSize/input->frameSize();                        
+                LOGV("RecordThread: loop starting");
+                continue;
+            }
+            if (mActiveTrack != 0) {
+                if (mActiveTrack->mState == TrackBase::PAUSING) {
+                    mActiveTrack.clear();
+                    mStartStopCond.broadcast();
+                } else if (mActiveTrack->mState == TrackBase::RESUMING) {
+                    mRsmpInIndex = mFrameCount;
+                    if (mReqChannelCount != mActiveTrack->channelCount()) {
+                        mActiveTrack.clear();
+                    } else {
+                        mActiveTrack->mState == TrackBase::ACTIVE;
+                    }
+                    mStartStopCond.broadcast();
+                }
+                mStandby = false;
+            }
+        }
+
+        if (mActiveTrack != 0) {
+            buffer.frameCount = mFrameCount;
+            if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
+                size_t framesOut = buffer.frameCount;
+                if (mResampler == 0) {
+                    // no resampling
+                    while (framesOut) {
+                        size_t framesIn = mFrameCount - mRsmpInIndex;
+                        if (framesIn) {
+                            int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
+                            int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
+                            if (framesIn > framesOut)
+                                framesIn = framesOut;
+                            mRsmpInIndex += framesIn;
+                            framesOut -= framesIn;
+                            if (mChannelCount == mReqChannelCount ||
+                                mFormat != AudioSystem::PCM_16_BIT) {
+                                memcpy(dst, src, framesIn * mFrameSize);
+                            } else {
+                                int16_t *src16 = (int16_t *)src;
+                                int16_t *dst16 = (int16_t *)dst;
+                                if (mChannelCount == 1) {
+                                    while (framesIn--) {
+                                        *dst16++ = *src16;
+                                        *dst16++ = *src16++;
+                                    }
+                                } else {
+                                    while (framesIn--) {
+                                        *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
+                                        src16 += 2;
+                                    }
+                                }
+                            }
+                        }
+                        if (framesOut && mFrameCount == mRsmpInIndex) {
+                            ssize_t bytesRead;
+                            if (framesOut == mFrameCount &&
+                                (mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
+                                bytesRead = mInput->read(buffer.raw, mInputBytes);
+                                framesOut = 0;
+                            } else {
+                                bytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
+                                mRsmpInIndex = 0;
+                            }
+                            if (bytesRead < 0) {
+                                LOGE("Error reading audio input");
+                                sleep(1);
+                                mRsmpInIndex = mFrameCount;
+                                framesOut = 0;
+                                buffer.frameCount = 0;
+                            }
+                        }
                     }
                 } else {
-                    mStartStatus = NO_INIT;
-                }
-                if (mStartStatus !=NO_ERROR) {
-                    LOGW("record start failed, status %d", mStartStatus);
-                    mActive = false;
-                    mRecordTrack.clear();                    
-                }
-                mWaitWorkCV.signal();
-            }
-            mLock.unlock();
-        } else if (mRecordTrack != 0) {
+                    // resampling
 
-            buffer.frameCount = inFrameCount;
-            if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR &&
-                       (int)buffer.frameCount == inFrameCount)) {
-                LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
-                ssize_t bytesRead = input->read(buffer.raw, inBufferSize);
-                if (bytesRead < 0) {
-                    LOGE("Error reading audio input");
-                    sleep(1);
-                }
-                mRecordTrack->releaseBuffer(&buffer);
-                mRecordTrack->overflow();
-            }
+                    memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
+                    // alter output frame count as if we were expecting stereo samples
+                    if (mChannelCount == 1 && mReqChannelCount == 1) {
+                        framesOut >>= 1;
+                    }
+                    mResampler->resample(mRsmpOutBuffer, framesOut, this);
+                    // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
+                    // are 32 bit aligned which should be always true.
+                    if (mChannelCount == 2 && mReqChannelCount == 1) {
+                        AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
+                        // the resampler always outputs stereo samples: do post stereo to mono conversion
+                        int16_t *src = (int16_t *)mRsmpOutBuffer;
+                        int16_t *dst = buffer.i16;
+                        while (framesOut--) {
+                            *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
+                            src += 2;
+                        }
+                    } else {
+                        AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
+                    }
 
+                }
+                mActiveTrack->releaseBuffer(&buffer);
+                mActiveTrack->overflow();
+            }
             // client isn't retrieving buffers fast enough
             else {
-                if (!mRecordTrack->setOverflow())
-                    LOGW("AudioRecordThread: buffer overflow");
+                if (!mActiveTrack->setOverflow())
+                    LOGW("RecordThread: buffer overflow");
                 // Release the processor for a while before asking for a new buffer.
                 // This will give the application more chance to read from the buffer and
                 // clear the overflow.
@@ -2466,65 +2972,64 @@
         }
     }
 
-
-    if (input) {
-        delete input;
+    if (!mStandby) {
+        mInput->standby();
     }
-    mRecordTrack.clear();
-    
+    mActiveTrack.clear();
+
+    sendConfigEvent(AudioSystem::INPUT_CLOSED);
+    processConfigEvents();
+
+    LOGV("RecordThread %p exiting", this);
     return false;
 }
 
-status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* recordTrack)
+status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
 {
-    LOGV("AudioRecordThread::start");
+    LOGV("RecordThread::start");
     AutoMutex lock(&mLock);
-    mActive = true;
-    // If starting the active track, just reset mActive in case a stop
-    // was pending and exit
-    if (recordTrack == mRecordTrack.get()) return NO_ERROR;
 
-    if (mRecordTrack != 0) return -EBUSY;
+    if (mActiveTrack != 0) {
+        if (recordTrack != mActiveTrack.get()) return -EBUSY;
 
-    mRecordTrack = recordTrack;
+        if (mActiveTrack->mState == TrackBase::PAUSING) mActiveTrack->mState = TrackBase::RESUMING;
 
+        return NO_ERROR;
+    }
+
+    mActiveTrack = recordTrack;
+    mActiveTrack->mState = TrackBase::RESUMING;
     // signal thread to start
     LOGV("Signal record thread");
     mWaitWorkCV.signal();
-    mWaitWorkCV.wait(mLock);
-    LOGV("Record started, status %d", mStartStatus);
-    return mStartStatus;
+    mStartStopCond.wait(mLock);
+    if (mActiveTrack != 0) {
+        LOGV("Record started OK");
+        return NO_ERROR;
+    } else {
+        LOGV("Record failed to start");
+        return BAD_VALUE;
+    }
 }
 
-void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack) {
-    LOGV("AudioRecordThread::stop");
+void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
+    LOGV("RecordThread::stop");
     AutoMutex lock(&mLock);
-    if (mActive && (recordTrack == mRecordTrack.get())) {
-        mActive = false;
-        mStopped.wait(mLock);
+    if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
+        mActiveTrack->mState = TrackBase::PAUSING;
+        mStartStopCond.wait(mLock);
     }
 }
 
-void AudioFlinger::AudioRecordThread::exit()
-{
-    LOGV("AudioRecordThread::exit");
-    {
-        AutoMutex lock(&mLock);
-        requestExit();
-        mWaitWorkCV.signal();
-    }
-    requestExitAndWait();
-}
-
-status_t AudioFlinger::AudioRecordThread::dump(int fd, const Vector<String16>& args)
+status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
     pid_t pid = 0;
 
-    if (mRecordTrack != 0 && mRecordTrack->mClient != 0) {
-        snprintf(buffer, SIZE, "Record client pid: %d\n", mRecordTrack->mClient->pid());
+    if (mActiveTrack != 0 && mActiveTrack->mClient != 0) {
+        snprintf(buffer, SIZE, "Record client pid: %d\n", mActiveTrack->mClient->pid());
         result.append(buffer);
     } else {
         result.append("No record client\n");
@@ -2533,6 +3038,463 @@
     return NO_ERROR;
 }
 
+status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+{
+    size_t framesReq = buffer->frameCount;
+    size_t framesReady = mFrameCount - mRsmpInIndex;
+    int channelCount;
+
+    if (framesReady == 0) {
+        ssize_t bytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
+        if (bytesRead < 0) {
+            LOGE("RecordThread::getNextBuffer() Error reading audio input");
+            sleep(1);
+            buffer->raw = 0;
+            buffer->frameCount = 0;
+            return NOT_ENOUGH_DATA;
+        }
+        mRsmpInIndex = 0;
+        framesReady = mFrameCount;
+    }
+
+    if (framesReq > framesReady) {
+        framesReq = framesReady;
+    }
+
+    if (mChannelCount == 1 && mReqChannelCount == 2) {
+        channelCount = 1;
+    } else {
+        channelCount = 2;
+    }
+    buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
+    buffer->frameCount = framesReq;
+    return NO_ERROR;
+}
+
+void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+{
+    mRsmpInIndex += buffer->frameCount;
+    buffer->frameCount = 0;
+}
+
+bool AudioFlinger::RecordThread::checkForNewParameters_l()
+{
+    bool reconfig = false;
+
+    if (mNewParameters != "") {
+        status_t status = NO_ERROR;
+        AudioParameter param = AudioParameter(mNewParameters);
+        int value;
+        int reqFormat = mFormat;
+        int reqSamplingRate = mReqSampleRate;
+        int reqChannelCount = mReqChannelCount;
+        if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
+            reqSamplingRate = value;
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
+            reqFormat = value;
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
+            reqChannelCount = AudioSystem::popCount(value);
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+            // do not accept frame count changes if tracks are open as the track buffer
+            // size depends on frame count and correct behavior would not be garantied
+            // if frame count is changed after track creation
+            if (mActiveTrack != 0) {
+                status = INVALID_OPERATION;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (status == NO_ERROR) {
+            status = mInput->setParameters(mNewParameters);
+            if (status == INVALID_OPERATION) {
+               mInput->standby();
+               status = mInput->setParameters(mNewParameters);
+            }
+            if (reconfig) {
+                if (status == BAD_VALUE &&
+                    reqFormat == mInput->format() && reqFormat == AudioSystem::PCM_16_BIT &&
+                    ((int)mInput->sampleRate() <= 2 * reqSamplingRate) &&
+                    (AudioSystem::popCount(mInput->channels()) < 3) && (reqChannelCount < 3)) {
+                    status = NO_ERROR;
+                }
+                if (status == NO_ERROR) {
+                    readInputParameters();
+                    sendConfigEvent(AudioSystem::INPUT_CONFIG_CHANGED);
+                }
+            }
+        }
+        mNewParameters = "";
+        mParamStatus = status;
+        mParamCond.signal();
+    }
+    return reconfig;
+}
+
+String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
+{
+    return mInput->getParameters(keys);
+}
+
+void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) {
+    AudioSystem::OutputDescriptor desc;
+    void *param2 = 0;
+
+    switch (event) {
+    case AudioSystem::INPUT_OPENED:
+    case AudioSystem::INPUT_CONFIG_CHANGED:
+        desc.channels = mChannelCount;
+        desc.samplingRate = mSampleRate;
+        desc.format = mFormat;
+        desc.frameCount = mFrameCount;
+        desc.latency = 0;
+        param2 = &desc;
+        break;
+
+    case AudioSystem::INPUT_CLOSED:
+    default:
+        break;
+    }
+    mAudioFlinger->audioConfigChanged(event, this, param2);
+}
+
+void AudioFlinger::RecordThread::readInputParameters()
+{
+    if (mRsmpInBuffer) delete mRsmpInBuffer;
+    if (mRsmpOutBuffer) delete mRsmpOutBuffer;
+    if (mResampler) delete mResampler;
+    mResampler = 0;
+
+    mSampleRate = mInput->sampleRate();
+    mChannelCount = AudioSystem::popCount(mInput->channels());
+    mFormat = mInput->format();
+    mFrameSize = mInput->frameSize();
+    mInputBytes = mInput->bufferSize();
+    mFrameCount = mInputBytes / mFrameSize;
+    mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
+
+    if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
+    {
+        int channelCount;
+         // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
+         // stereo to mono post process as the resampler always outputs stereo.
+        if (mChannelCount == 1 && mReqChannelCount == 2) {
+            channelCount = 1;
+        } else {
+            channelCount = 2;
+        }
+        mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
+        mResampler->setSampleRate(mSampleRate);
+        mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
+        mRsmpOutBuffer = new int32_t[mFrameCount * 2];
+
+        // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
+        if (mChannelCount == 1 && mReqChannelCount == 1) {
+            mFrameCount >>= 1;
+        }
+
+    }
+    mRsmpInIndex = mFrameCount;
+}
+
+// ----------------------------------------------------------------------------
+
+void *AudioFlinger::openOutput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t *pLatencyMs,
+                                uint32_t flags)
+{
+    status_t status;
+    PlaybackThread *thread = NULL;
+    mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
+    uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+    uint32_t format = pFormat ? *pFormat : 0;
+    uint32_t channels = pChannels ? *pChannels : 0;
+    uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
+
+    LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
+            pDevices ? *pDevices : 0,
+            samplingRate,
+            format,
+            channels,
+            flags);
+
+    if (pDevices == NULL || *pDevices == 0) {
+        return NULL;
+    }
+    Mutex::Autolock _l(mLock);
+
+    AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
+                                                             (int *)&format,
+                                                             &channels,
+                                                             &samplingRate,
+                                                             &status);
+    LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
+            output,
+            samplingRate,
+            format,
+            channels,
+            status);
+
+    mHardwareStatus = AUDIO_HW_IDLE;
+    if (output != 0) {
+        if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
+            (format != AudioSystem::PCM_16_BIT) ||
+            (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
+            thread = new DirectOutputThread(this, output);
+            LOGV("openOutput() created direct output %p", thread);
+        } else {
+            thread = new MixerThread(this, output);
+            LOGV("openOutput() created mixer output %p", thread);
+        }
+        mPlaybackThreads.add(thread);
+
+        if (pSamplingRate) *pSamplingRate = samplingRate;
+        if (pFormat) *pFormat = format;
+        if (pChannels) *pChannels = channels;
+        if (pLatencyMs) *pLatencyMs = thread->latency();
+    }
+
+    return thread;
+}
+
+void *AudioFlinger::openDuplicateOutput(void *output1, void *output2)
+{
+    Mutex::Autolock _l(mLock);
+
+    if (checkMixerThread_l(output1) == NULL ||
+        checkMixerThread_l(output2) == NULL) {
+        LOGW("openDuplicateOutput() wrong output mixer type %p or %p", output1, output2);
+        return NULL;
+    }
+
+    DuplicatingThread *thread = new DuplicatingThread(this, (MixerThread *)output1);
+    thread->addOutputTrack( (MixerThread *)output2);
+    mPlaybackThreads.add(thread);
+    return thread;
+}
+
+status_t AudioFlinger::closeOutput(void *output)
+{
+    PlaybackThread *thread;
+    {
+        Mutex::Autolock _l(mLock);
+        thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            return BAD_VALUE;
+        }
+
+        LOGV("closeOutput() %p", thread);
+
+        if (thread->type() == PlaybackThread::MIXER) {
+            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+                if (mPlaybackThreads[i]->type() == PlaybackThread::DUPLICATING) {
+                    DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads[i].get();
+                    dupThread->removeOutputTrack((MixerThread *)thread);
+                }
+            }
+        }
+        mPlaybackThreads.remove(thread);
+    }
+    thread->exit();
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::suspendOutput(void *output)
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+
+    if (thread == NULL) {
+        return BAD_VALUE;
+    }
+
+    LOGV("suspendOutput() %p", output);
+    thread->suspend();
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::restoreOutput(void *output)
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+
+    if (thread == NULL) {
+        return BAD_VALUE;
+    }
+
+    LOGV("restoreOutput() %p", output);
+
+    thread->restore();
+
+    return NO_ERROR;
+}
+
+void *AudioFlinger::openInput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t acoustics)
+{
+    status_t status;
+    RecordThread *thread = NULL;
+    uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+    uint32_t format = pFormat ? *pFormat : 0;
+    uint32_t channels = pChannels ? *pChannels : 0;
+    uint32_t reqSamplingRate = samplingRate;
+    uint32_t reqFormat = format;
+    uint32_t reqChannels = channels;
+
+    if (pDevices == NULL || *pDevices == 0) {
+        return NULL;
+    }
+    Mutex::Autolock _l(mLock);
+
+    AudioStreamIn *input = mAudioHardware->openInputStream(*pDevices,
+                                                             (int *)&format,
+                                                             &channels,
+                                                             &samplingRate,
+                                                             &status,
+                                                             (AudioSystem::audio_in_acoustics)acoustics);
+    LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
+            input,
+            samplingRate,
+            format,
+            channels,
+            acoustics,
+            status);
+
+    // If the input could not be opened with the requested parameters and we can handle the conversion internally,
+    // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
+    // or stereo to mono conversions on 16 bit PCM inputs.
+    if (input == 0 && status == BAD_VALUE &&
+        reqFormat == format && format == AudioSystem::PCM_16_BIT &&
+        (samplingRate <= 2 * reqSamplingRate) &&
+        (AudioSystem::popCount(channels) < 3) && (AudioSystem::popCount(reqChannels) < 3)) {
+        LOGV("openInput() reopening with proposed sampling rate and channels");
+        input = mAudioHardware->openInputStream(*pDevices,
+                                                 (int *)&format,
+                                                 &channels,
+                                                 &samplingRate,
+                                                 &status,
+                                                 (AudioSystem::audio_in_acoustics)acoustics);
+    }
+
+    if (input != 0) {
+         // Start record thread
+        thread = new RecordThread(this, input, reqSamplingRate, reqChannels);
+        mRecordThreads.add(thread);
+
+        if (pSamplingRate) *pSamplingRate = reqSamplingRate;
+        if (pFormat) *pFormat = format;
+        if (pChannels) *pChannels = reqChannels;
+
+        input->standby();
+    }
+
+    return thread;
+}
+
+status_t AudioFlinger::closeInput(void *input)
+{
+    RecordThread *thread;
+    {
+        Mutex::Autolock _l(mLock);
+        thread = checkRecordThread_l(input);
+        if (thread == NULL) {
+            return BAD_VALUE;
+        }
+
+        LOGV("closeInput() %p", thread);
+        mRecordThreads.remove(thread);
+    }
+    thread->exit();
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::setStreamOutput(uint32_t stream, void *output)
+{
+    Mutex::Autolock _l(mLock);
+    MixerThread *dstThread = checkMixerThread_l(output);
+    if (dstThread == NULL) {
+        LOGW("setStreamOutput() bad output thread %p", output);
+        return BAD_VALUE;
+    }
+
+    LOGV("setStreamOutput() stream %d to output %p", stream, dstThread);
+
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        PlaybackThread *thread = mPlaybackThreads[i].get();
+        if (thread != dstThread &&
+            thread->type() != PlaybackThread::DIRECT) {
+            MixerThread *srcThread = (MixerThread *)thread;
+            SortedVector < sp<MixerThread::Track> > tracks;
+            SortedVector < wp<MixerThread::Track> > activeTracks;
+            srcThread->getTracks(tracks, activeTracks, stream);
+            if (tracks.size()) {
+                dstThread->putTracks(tracks, activeTracks);
+                dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream);
+            }
+        }
+    }
+
+    return NO_ERROR;
+}
+
+// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(void *output) const
+{
+    PlaybackThread *thread = NULL;
+
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        if (mPlaybackThreads[i] == output) {
+            thread = (PlaybackThread *)output;
+            break;
+        }
+    }
+
+    return thread;
+}
+
+// checkMixerThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(void *output) const
+{
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread != NULL) {
+        if (thread->type() == PlaybackThread::DIRECT) {
+            thread = NULL;
+        }
+    }
+    return (MixerThread *)thread;
+}
+
+// checkRecordThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(void *input) const
+{
+    RecordThread *thread = NULL;
+
+    for (size_t i = 0; i < mRecordThreads.size(); i++) {
+        if (mRecordThreads[i] == input) {
+            thread = (RecordThread *)input;
+            break;
+        }
+    }
+
+    return thread;
+}
+
+// ----------------------------------------------------------------------------
+
 status_t AudioFlinger::onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
@@ -2540,6 +3502,7 @@
 }
 
 // ----------------------------------------------------------------------------
+
 void AudioFlinger::instantiate() {
     defaultServiceManager()->addService(
             String16("media.audio_flinger"), new AudioFlinger());
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 3531a58..06c5846 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -31,7 +31,6 @@
 #include <utils/Errors.h>
 #include <utils/threads.h>
 #include <binder/MemoryDealer.h>
-#include <utils/KeyedVector.h>
 #include <utils/SortedVector.h>
 #include <utils/Vector.h>
 
@@ -44,6 +43,7 @@
 class audio_track_cblk_t;
 class AudioMixer;
 class AudioBuffer;
+class AudioResampler;
 
 
 // ----------------------------------------------------------------------------
@@ -56,7 +56,7 @@
 
 static const nsecs_t kStandbyTimeInNsecs = seconds(3);
 
-class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient 
+class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient
 {
 public:
     static void instantiate();
@@ -73,13 +73,14 @@
                                 int frameCount,
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
+                                void *output,
                                 status_t *status);
 
-    virtual     uint32_t    sampleRate(int output) const;
-    virtual     int         channelCount(int output) const;
-    virtual     int         format(int output) const;
-    virtual     size_t      frameCount(int output) const;
-    virtual     uint32_t    latency(int output) const;
+    virtual     uint32_t    sampleRate(void *output) const;
+    virtual     int         channelCount(void *output) const;
+    virtual     int         format(void *output) const;
+    virtual     size_t      frameCount(void *output) const;
+    virtual     uint32_t    latency(void *output) const;
 
     virtual     status_t    setMasterVolume(float value);
     virtual     status_t    setMasterMute(bool muted);
@@ -87,33 +88,51 @@
     virtual     float       masterVolume() const;
     virtual     bool        masterMute() const;
 
-    virtual     status_t    setStreamVolume(int stream, float value);
+    virtual     status_t    setStreamVolume(int stream, float value, void *output);
     virtual     status_t    setStreamMute(int stream, bool muted);
 
-    virtual     float       streamVolume(int stream) const;
+    virtual     float       streamVolume(int stream, void *output) const;
     virtual     bool        streamMute(int stream) const;
 
-    virtual     status_t    setRouting(int mode, uint32_t routes, uint32_t mask);
-    virtual     uint32_t    getRouting(int mode) const;
-
     virtual     status_t    setMode(int mode);
-    virtual     int         getMode() const;
 
     virtual     status_t    setMicMute(bool state);
     virtual     bool        getMicMute() const;
 
     virtual     bool        isMusicActive() const;
 
-    virtual     bool        isA2dpEnabled() const;
-
-    virtual     status_t    setParameter(const char* key, const char* value);
+    virtual     status_t    setParameters(void *ioHandle, const String8& keyValuePairs);
+    virtual     String8     getParameters(void *ioHandle, const String8& keys);
 
     virtual     void        registerClient(const sp<IAudioFlingerClient>& client);
-    
+
     virtual     size_t      getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
-    
-    virtual     void        wakeUp()    { mWaitWorkCV.broadcast(); }
-    
+
+    virtual void *openOutput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t *pLatencyMs,
+                                    uint32_t flags);
+
+    virtual void *openDuplicateOutput(void *output1, void *output2);
+
+    virtual status_t closeOutput(void *output);
+
+    virtual status_t suspendOutput(void *output);
+
+    virtual status_t restoreOutput(void *output);
+
+    virtual void *openInput(uint32_t *pDevices,
+                            uint32_t *pSamplingRate,
+                            uint32_t *pFormat,
+                            uint32_t *pChannels,
+                            uint32_t acoustics);
+
+    virtual status_t closeInput(void *input);
+
+    virtual status_t setStreamOutput(uint32_t stream, void *output);
+
     // IBinder::DeathRecipient
     virtual     void        binderDied(const wp<IBinder>& who);
 
@@ -139,7 +158,7 @@
     // record interface
     virtual sp<IAudioRecord> openRecord(
                                 pid_t pid,
-                                int inputSource,
+                                void *input,
                                 uint32_t sampleRate,
                                 int format,
                                 int channelCount,
@@ -153,30 +172,12 @@
                                 Parcel* reply,
                                 uint32_t flags);
 
+    void audioConfigChanged(int event, void *param1, void *param2);
+
 private:
                             AudioFlinger();
     virtual                 ~AudioFlinger();
-    
-    void                    setOutput(int outputType);
-    void                    doSetOutput(int outputType);
 
-#ifdef WITH_A2DP
-    void                    setA2dpEnabled_l(bool enable);
-    void                    checkA2dpEnabledChange_l();
-#endif
-    static bool             streamForcedToSpeaker(int streamType);
-    
-    // Management of forced route to speaker for certain track types.
-    enum force_speaker_command {
-        ACTIVE_TRACK_ADDED = 0,
-        ACTIVE_TRACK_REMOVED,
-        CHECK_ROUTE_RESTORE_TIME,
-        FORCE_ROUTE_RESTORE
-    };
-    void                    handleForcedSpeakerRoute(int command);
-#ifdef WITH_A2DP
-    void                    handleRouteDisablesA2dp_l(int routes);
-#endif
 
     // Internal dump utilites.
     status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
@@ -201,14 +202,17 @@
 
     class TrackHandle;
     class RecordHandle;
-    class AudioRecordThread;
+    class RecordThread;
+    class PlaybackThread;
+    class MixerThread;
+    class DirectOutputThread;
+    class Track;
+    class RecordTrack;
 
-    
-    // --- MixerThread ---
-    class MixerThread : public Thread {
+    class ThreadBase : public Thread {
     public:
-        
-        // --- Track ---
+        ThreadBase (const sp<AudioFlinger>& audioFlinger);
+        virtual             ~ThreadBase();
 
         // base for record and playback
         class TrackBase : public AudioBufferProvider, public RefBase {
@@ -230,7 +234,7 @@
                 // The upper 16 bits are used for track-specific flags.
             };
 
-                                TrackBase(const sp<MixerThread>& mixerThread,
+                                TrackBase(const wp<ThreadBase>& thread,
                                         const sp<Client>& client,
                                         uint32_t sampleRate,
                                         int format,
@@ -245,9 +249,12 @@
                     sp<IMemory> getCblk() const;
 
         protected:
-            friend class MixerThread;
+            friend class ThreadBase;
             friend class RecordHandle;
-            friend class AudioRecordThread;
+            friend class PlaybackThread;
+            friend class RecordThread;
+            friend class MixerThread;
+            friend class DirectOutputThread;
 
                                 TrackBase(const TrackBase&);
                                 TrackBase& operator = (const TrackBase&);
@@ -269,10 +276,6 @@
 
             void* getBuffer(uint32_t offset, uint32_t frames) const;
 
-            int name() const {
-                return mName;
-            }
-
             bool isStopped() const {
                 return mState == STOPPED;
             }
@@ -284,14 +287,13 @@
             bool step();
             void reset();
 
-            sp<MixerThread>     mMixerThread;
+            wp<ThreadBase>      mThread;
             sp<Client>          mClient;
             sp<IMemory>         mCblkMemory;
             audio_track_cblk_t* mCblk;
             void*               mBuffer;
             void*               mBufferEnd;
             uint32_t            mFrameCount;
-            int                 mName;
             // we don't really need a lock for these
             int                 mState;
             int                 mClientTid;
@@ -299,10 +301,68 @@
             uint32_t            mFlags;
         };
 
+        class ConfigEvent {
+        public:
+            ConfigEvent() : mEvent(0), mParam(0) {}
+
+            int mEvent;
+            int mParam;
+        };
+
+                    uint32_t    sampleRate() const;
+                    int         channelCount() const;
+                    int         format() const;
+                    size_t      frameCount() const;
+                    void        wakeUp()    { mWaitWorkCV.broadcast(); }
+                    void        exit();
+        virtual     bool        checkForNewParameters_l() = 0;
+        virtual     status_t    setParameters(const String8& keyValuePairs);
+        virtual     String8     getParameters(const String8& keys) = 0;
+        virtual     void        audioConfigChanged(int event, int param = 0) = 0;
+                    void        sendConfigEvent(int event, int param = 0);
+                    void        processConfigEvents();
+
+        mutable     Mutex                   mLock;
+
+    protected:
+
+        friend class Track;
+        friend class TrackBase;
+        friend class PlaybackThread;
+        friend class MixerThread;
+        friend class DirectOutputThread;
+        friend class DuplicatingThread;
+        friend class RecordThread;
+        friend class RecordTrack;
+
+                    Condition               mWaitWorkCV;
+                    sp<AudioFlinger>        mAudioFlinger;
+                    uint32_t                mSampleRate;
+                    size_t                  mFrameCount;
+                    int                     mChannelCount;
+                    int                     mFormat;
+                    uint32_t                mFrameSize;
+                    Condition               mParamCond;
+                    String8                 mNewParameters;
+                    status_t                mParamStatus;
+                    Vector<ConfigEvent *>   mConfigEvents;
+                    bool                    mStandby;
+    };
+
+    // --- PlaybackThread ---
+    class PlaybackThread : public ThreadBase {
+    public:
+
+        enum type {
+            MIXER,
+            DIRECT,
+            DUPLICATING
+        };
+
         // playback track
         class Track : public TrackBase {
         public:
-                                Track(  const sp<MixerThread>& mixerThread,
+                                Track(  const wp<ThreadBase>& thread,
                                         const sp<Client>& client,
                                         int streamType,
                                         uint32_t sampleRate,
@@ -321,6 +381,9 @@
                     void        destroy();
                     void        mute(bool);
                     void        setVolume(float left, float right);
+                    int name() const {
+                        return mName;
+                    }
 
                     int type() const {
                         return mStreamType;
@@ -328,29 +391,25 @@
 
 
         protected:
-            friend class MixerThread;
+            friend class ThreadBase;
             friend class AudioFlinger;
-            friend class AudioFlinger::TrackHandle;
+            friend class TrackHandle;
+            friend class PlaybackThread;
+            friend class MixerThread;
+            friend class DirectOutputThread;
 
                                 Track(const Track&);
                                 Track& operator = (const Track&);
 
             virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-
-            bool isMuted() const {
-                return (mMute || mMixerThread->mStreamTypes[mStreamType].mute);
-            }
-
+            bool isMuted() { return mMute; }
             bool isPausing() const {
                 return mState == PAUSING;
             }
-
             bool isPaused() const {
                 return mState == PAUSED;
             }
-
             bool isReady() const;
-
             void setPaused() { mState = PAUSED; }
             void reset();
 
@@ -364,54 +423,20 @@
             sp<IMemory>         mSharedBuffer;
             bool                mResetDone;
             int                 mStreamType;
+            int                 mName;
         };  // end of Track
 
-        // record track
-        class RecordTrack : public TrackBase {
-        public:
-                                RecordTrack(const sp<MixerThread>& mixerThread,
-                                        const sp<Client>& client,
-                                        int inputSource,
-                                        uint32_t sampleRate,
-                                        int format,
-                                        int channelCount,
-                                        int frameCount,
-                                        uint32_t flags);
-                                ~RecordTrack();
-
-            virtual status_t    start();
-            virtual void        stop();
-
-                    bool        overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
-                    bool        setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
-
-                    int         inputSource() const { return mInputSource; }
-
-        private:
-            friend class AudioFlinger;
-            friend class AudioFlinger::RecordHandle;
-            friend class AudioFlinger::AudioRecordThread;
-            friend class MixerThread;
-
-                                RecordTrack(const Track&);
-                                RecordTrack& operator = (const Track&);
-
-            virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-
-            bool                mOverflow;
-            int                 mInputSource;
-        };
 
         // playback track
         class OutputTrack : public Track {
         public:
-            
+
             class Buffer: public AudioBufferProvider::Buffer {
             public:
                 int16_t *mBuffer;
             };
-            
-                                OutputTrack(  const sp<MixerThread>& mixerThread,
+
+                                OutputTrack(  const wp<ThreadBase>& thread,
                                         uint32_t sampleRate,
                                         int format,
                                         int channelCount,
@@ -420,35 +445,35 @@
 
             virtual status_t    start();
             virtual void        stop();
-                    void        write(int16_t* data, uint32_t frames);
+                    bool        write(int16_t* data, uint32_t frames);
                     bool        bufferQueueEmpty() { return (mBufferQueue.size() == 0) ? true : false; }
+                    bool        isActive() { return mActive; }
+            wp<ThreadBase>&     thread()  { return mThread; }
 
         private:
 
-            status_t            obtainBuffer(AudioBufferProvider::Buffer* buffer);
+            status_t            obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs);
             void                clearBufferQueue();
-            
-            sp<MixerThread>             mOutputMixerThread;
+
+            // Maximum number of pending buffers allocated by OutputTrack::write()
+            static const uint8_t kMaxOverFlowBuffers = 3;
+
             Vector < Buffer* >          mBufferQueue;
             AudioBufferProvider::Buffer mOutBuffer;
-            uint32_t                    mFramesWritten;
-            
-         };  // end of OutputTrack
+            uint32_t                    mWaitTimeMs;
+            bool                        mActive;
 
-        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType);
-        virtual             ~MixerThread();
+        };  // end of OutputTrack
+
+        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        virtual             ~PlaybackThread();
 
         virtual     status_t    dump(int fd, const Vector<String16>& args);
 
         // Thread virtuals
-        virtual     bool        threadLoop();
         virtual     status_t    readyToRun();
         virtual     void        onFirstRef();
 
-        virtual     uint32_t    sampleRate() const;
-        virtual     int         channelCount() const;
-        virtual     int         format() const;
-        virtual     size_t      frameCount() const;
         virtual     uint32_t    latency() const;
 
         virtual     status_t    setMasterVolume(float value);
@@ -463,9 +488,8 @@
         virtual     float       streamVolume(int stream) const;
         virtual     bool        streamMute(int stream) const;
 
-                    bool        isMusicActive_l() const;
-        
-                    
+                    bool        isMusicActive() const;
+
                     sp<Track>   createTrack_l(
                                     const sp<AudioFlinger::Client>& client,
                                     int streamType,
@@ -475,13 +499,15 @@
                                     int frameCount,
                                     const sp<IMemory>& sharedBuffer,
                                     status_t *status);
-                    
-                    void        getTracks_l(SortedVector < sp<Track> >& tracks,
-                                          SortedVector < wp<Track> >& activeTracks);
-                    void        putTracks_l(SortedVector < sp<Track> >& tracks,
-                                          SortedVector < wp<Track> >& activeTracks);
-                    void        setOuputTrack(OutputTrack *track) { mOutputTrack = track; }
-                    
+
+                    AudioStreamOut* getOutput() { return mOutput; }
+
+        virtual     int         type() const { return mType; }
+                    void        suspend() { mSuspended = true; }
+                    void        restore() { mSuspended = false; }
+        virtual     String8     getParameters(const String8& keys);
+        virtual     void        audioConfigChanged(int event, int param = 0);
+
         struct  stream_type_t {
             stream_type_t()
                 :   volume(1.0f),
@@ -492,56 +518,113 @@
             bool        mute;
         };
 
-    private:
+    protected:
+        int                             mType;
+        int16_t*                        mMixBuffer;
+        bool                            mSuspended;
+        int                             mBytesWritten;
+        bool                            mMasterMute;
+        SortedVector< wp<Track> >       mActiveTracks;
 
+    private:
 
         friend class AudioFlinger;
         friend class Track;
         friend class TrackBase;
-        friend class RecordTrack;
-        
-        MixerThread(const Client&);
-        MixerThread& operator = (const MixerThread&);
-  
+        friend class MixerThread;
+        friend class DirectOutputThread;
+        friend class DuplicatingThread;
+
+        PlaybackThread(const Client&);
+        PlaybackThread& operator = (const PlaybackThread&);
+
         status_t    addTrack_l(const sp<Track>& track);
         void        destroyTrack_l(const sp<Track>& track);
-        int         getTrackName_l();
-        void        deleteTrackName_l(int name);
-        void        addActiveTrack_l(const wp<Track>& t);
-        void        removeActiveTrack_l(const wp<Track>& t);
-        size_t      getOutputFrameCount();
+        virtual int         getTrackName_l() = 0;
+        virtual void        deleteTrackName_l(int name) = 0;
+        void        readOutputParameters();
 
-        status_t    dumpInternals(int fd, const Vector<String16>& args);
+        virtual status_t    dumpInternals(int fd, const Vector<String16>& args);
         status_t    dumpTracks(int fd, const Vector<String16>& args);
-        
-        sp<AudioFlinger>                mAudioFlinger;       
-        SortedVector< wp<Track> >       mActiveTracks;
+
         SortedVector< sp<Track> >       mTracks;
-        stream_type_t                   mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
-        AudioMixer*                     mAudioMixer;
+        // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
+        stream_type_t                   mStreamTypes[AudioSystem::NUM_STREAM_TYPES + 1];
         AudioStreamOut*                 mOutput;
-        int                             mOutputType;
-        uint32_t                        mSampleRate;
-        size_t                          mFrameCount;
-        int                             mChannelCount;
-        int                             mFormat;
-        int16_t*                        mMixBuffer;
         float                           mMasterVolume;
-        bool                            mMasterMute;
         nsecs_t                         mLastWriteTime;
         int                             mNumWrites;
         int                             mNumDelayedWrites;
-        bool                            mStandby;
         bool                            mInWrite;
-        sp <OutputTrack>                mOutputTrack;
+        int                             mMinBytesToWrite;
     };
 
-    
+    class MixerThread : public PlaybackThread {
+    public:
+        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        virtual             ~MixerThread();
+
+        // Thread virtuals
+        virtual     bool        threadLoop();
+
+                    void        getTracks(SortedVector < sp<Track> >& tracks,
+                                      SortedVector < wp<Track> >& activeTracks,
+                                      int streamType);
+                    void        putTracks(SortedVector < sp<Track> >& tracks,
+                                      SortedVector < wp<Track> >& activeTracks);
+        virtual     int         getTrackName_l();
+        virtual     void        deleteTrackName_l(int name);
+        virtual     bool        checkForNewParameters_l();
+        virtual     status_t    dumpInternals(int fd, const Vector<String16>& args);
+
+    protected:
+        size_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
+
+        AudioMixer*                     mAudioMixer;
+    };
+
+    class DirectOutputThread : public PlaybackThread {
+    public:
+
+        DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        ~DirectOutputThread();
+
+        // Thread virtuals
+        virtual     bool        threadLoop();
+
+        virtual     int         getTrackName_l();
+        virtual     void        deleteTrackName_l(int name);
+        virtual     bool        checkForNewParameters_l();
+
+    private:
+        float mLeftVolume;
+        float mRightVolume;
+    };
+
+    class DuplicatingThread : public MixerThread {
+    public:
+        DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread);
+        ~DuplicatingThread();
+
+        // Thread virtuals
+        virtual     bool        threadLoop();
+                    void        addOutputTrack(MixerThread* thread);
+                    void        removeOutputTrack(MixerThread* thread);
+
+    private:
+        SortedVector < sp<OutputTrack> >  mOutputTracks;
+    };
+
+              PlaybackThread *checkPlaybackThread_l(void *output) const;
+              MixerThread *checkMixerThread_l(void *output) const;
+              RecordThread *checkRecordThread_l(void *input) const;
+              float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
+
     friend class AudioBuffer;
 
     class TrackHandle : public android::BnAudioTrack {
     public:
-                            TrackHandle(const sp<MixerThread::Track>& track);
+                            TrackHandle(const sp<PlaybackThread::Track>& track);
         virtual             ~TrackHandle();
         virtual status_t    start();
         virtual void        stop();
@@ -553,20 +636,91 @@
         virtual status_t onTransact(
             uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
     private:
-        sp<MixerThread::Track> mTrack;
+        sp<PlaybackThread::Track> mTrack;
     };
 
     friend class Client;
-    friend class MixerThread::Track;
+    friend class PlaybackThread::Track;
 
 
                 void        removeClient(pid_t pid);
 
 
+    // record thread
+    class RecordThread : public ThreadBase, public AudioBufferProvider
+    {
+    public:
+
+        // record track
+        class RecordTrack : public TrackBase {
+        public:
+                                RecordTrack(const wp<ThreadBase>& thread,
+                                        const sp<Client>& client,
+                                        uint32_t sampleRate,
+                                        int format,
+                                        int channelCount,
+                                        int frameCount,
+                                        uint32_t flags);
+                                ~RecordTrack();
+
+            virtual status_t    start();
+            virtual void        stop();
+
+                    bool        overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
+                    bool        setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
+
+        private:
+            friend class AudioFlinger;
+            friend class RecordThread;
+
+                                RecordTrack(const RecordTrack&);
+                                RecordTrack& operator = (const RecordTrack&);
+
+            virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
+
+            bool                mOverflow;
+        };
+
+
+                RecordThread(const sp<AudioFlinger>& audioFlinger,
+                        AudioStreamIn *input,
+                        uint32_t sampleRate,
+                        uint32_t channels);
+                ~RecordThread();
+
+        virtual bool        threadLoop();
+        virtual status_t    readyToRun() { return NO_ERROR; }
+        virtual void        onFirstRef();
+
+                status_t    start(RecordTrack* recordTrack);
+                void        stop(RecordTrack* recordTrack);
+                status_t    dump(int fd, const Vector<String16>& args);
+                AudioStreamIn* getInput() { return mInput; }
+
+        virtual status_t    getNextBuffer(AudioBufferProvider::Buffer* buffer);
+        virtual void        releaseBuffer(AudioBufferProvider::Buffer* buffer);
+        virtual bool        checkForNewParameters_l();
+        virtual String8     getParameters(const String8& keys);
+        virtual void        audioConfigChanged(int event, int param = 0);
+                void        readInputParameters();
+
+    private:
+                RecordThread();
+                AudioStreamIn                       *mInput;
+                sp<RecordTrack>                     mActiveTrack;
+                Condition                           mStartStopCond;
+                AudioResampler                      *mResampler;
+                int32_t                             *mRsmpOutBuffer;
+                int16_t                             *mRsmpInBuffer;
+                size_t                              mRsmpInIndex;
+                size_t                              mInputBytes;
+                int                                 mReqChannelCount;
+                uint32_t                            mReqSampleRate;
+    };
 
     class RecordHandle : public android::BnAudioRecord {
     public:
-        RecordHandle(const sp<MixerThread::RecordTrack>& recordTrack);
+        RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
         virtual             ~RecordHandle();
         virtual status_t    start();
         virtual void        stop();
@@ -574,66 +728,30 @@
         virtual status_t onTransact(
             uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
     private:
-        sp<MixerThread::RecordTrack> mRecordTrack;
+        sp<RecordThread::RecordTrack> mRecordTrack;
     };
 
-    // record thread
-    class AudioRecordThread : public Thread
-    {
-    public:
-        AudioRecordThread(AudioHardwareInterface* audioHardware, const sp<AudioFlinger>& audioFlinger);
-        virtual             ~AudioRecordThread();
-        virtual bool        threadLoop();
-        virtual status_t    readyToRun() { return NO_ERROR; }
-        virtual void        onFirstRef() {}
+    friend class RecordThread;
+    friend class PlaybackThread;
 
-                status_t    start(MixerThread::RecordTrack* recordTrack);
-                void        stop(MixerThread::RecordTrack* recordTrack);
-                void        exit();
-                status_t    dump(int fd, const Vector<String16>& args);
 
-    private:
-                AudioRecordThread();
-                AudioHardwareInterface              *mAudioHardware;
-                sp<AudioFlinger>                    mAudioFlinger;
-                sp<MixerThread::RecordTrack>        mRecordTrack;
-                Mutex                               mLock;
-                Condition                           mWaitWorkCV;
-                Condition                           mStopped;
-                volatile bool                       mActive;
-                status_t                            mStartStatus;
-    };
-
-    friend class AudioRecordThread;
-    friend class MixerThread;
-
-                status_t    startRecord(MixerThread::RecordTrack* recordTrack);
-                void        stopRecord(MixerThread::RecordTrack* recordTrack);
-
-    mutable     Mutex                               mHardwareLock;
     mutable     Mutex                               mLock;
-    mutable     Condition                           mWaitWorkCV;
 
                 DefaultKeyedVector< pid_t, wp<Client> >     mClients;
 
-                sp<MixerThread>                     mA2dpMixerThread;
-                sp<MixerThread>                     mHardwareMixerThread;
+                mutable     Mutex                   mHardwareLock;
                 AudioHardwareInterface*             mAudioHardware;
-                AudioHardwareInterface*             mA2dpAudioInterface;
-                sp<AudioRecordThread>               mAudioRecordThread;
-                bool                                mA2dpEnabled;
-                bool                                mNotifyA2dpChange;
     mutable     int                                 mHardwareStatus;
-                SortedVector< wp<IBinder> >         mNotificationClients;
-                int                                 mForcedSpeakerCount;
-                int                                 mA2dpDisableCount;
 
-                // true if A2DP should resume when mA2dpDisableCount returns to zero
-                bool                                mA2dpSuppressed;
-                uint32_t                            mSavedRoute;
-                uint32_t                            mForcedRoute;
-                nsecs_t                             mRouteRestoreTime;
-                bool                                mMusicMuteSaved;
+
+                SortedVector< sp<PlaybackThread> >  mPlaybackThreads;
+                PlaybackThread::stream_type_t       mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
+                float                               mMasterVolume;
+                bool                                mMasterMute;
+
+                SortedVector< sp<RecordThread> >    mRecordThreads;
+
+                SortedVector< sp<IBinder> >         mNotificationClients;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp
index 1e159b8..57874f3 100644
--- a/libs/audioflinger/AudioHardwareGeneric.cpp
+++ b/libs/audioflinger/AudioHardwareGeneric.cpp
@@ -49,8 +49,8 @@
 AudioHardwareGeneric::~AudioHardwareGeneric()
 {
     if (mFd >= 0) ::close(mFd);
-    delete mOutput;
-    delete mInput;
+    closeOutputStream((AudioStreamOut *)mOutput);
+    closeInputStream((AudioStreamIn *)mInput);
 }
 
 status_t AudioHardwareGeneric::initCheck()
@@ -63,7 +63,7 @@
 }
 
 AudioStreamOut* AudioHardwareGeneric::openOutputStream(
-        int format, int channelCount, uint32_t sampleRate, status_t *status)
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
 {
     AutoMutex lock(mLock);
 
@@ -77,7 +77,7 @@
 
     // create new output stream
     AudioStreamOutGeneric* out = new AudioStreamOutGeneric();
-    status_t lStatus = out->set(this, mFd, format, channelCount, sampleRate);
+    status_t lStatus = out->set(this, mFd, devices, format, channels, sampleRate);
     if (status) {
         *status = lStatus;
     }
@@ -89,17 +89,19 @@
     return mOutput;
 }
 
-void AudioHardwareGeneric::closeOutputStream(AudioStreamOutGeneric* out) {
-    if (out == mOutput) mOutput = 0;
+void AudioHardwareGeneric::closeOutputStream(AudioStreamOut* out) {
+    if (mOutput && out == mOutput) {
+        delete mOutput;
+        mOutput = 0;
+    }
 }
 
 AudioStreamIn* AudioHardwareGeneric::openInputStream(
-        int inputSource, int format, int channelCount, uint32_t sampleRate,
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
         status_t *status, AudioSystem::audio_in_acoustics acoustics)
 {
     // check for valid input source
-    if ((inputSource < AudioRecord::DEFAULT_INPUT) ||
-        (inputSource >= AudioRecord::NUM_INPUT_SOURCES)) {
+    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
         return 0;
     }
 
@@ -115,7 +117,7 @@
 
     // create new output stream
     AudioStreamInGeneric* in = new AudioStreamInGeneric();
-    status_t lStatus = in->set(this, mFd, format, channelCount, sampleRate, acoustics);
+    status_t lStatus = in->set(this, mFd, devices, format, channels, sampleRate, acoustics);
     if (status) {
         *status = lStatus;
     }
@@ -127,8 +129,11 @@
     return mInput;
 }
 
-void AudioHardwareGeneric::closeInputStream(AudioStreamInGeneric* in) {
-    if (in == mInput) mInput = 0;
+void AudioHardwareGeneric::closeInputStream(AudioStreamIn* in) {
+    if (mInput && in == mInput) {
+        delete mInput;
+        mInput = 0;
+    }
 }
 
 status_t AudioHardwareGeneric::setVoiceVolume(float v)
@@ -185,30 +190,42 @@
 status_t AudioStreamOutGeneric::set(
         AudioHardwareGeneric *hw,
         int fd,
-        int format,
-        int channels,
-        uint32_t rate)
+        uint32_t devices,
+        int *pFormat,
+        uint32_t *pChannels,
+        uint32_t *pRate)
 {
+    int lFormat = pFormat ? *pFormat : 0;
+    uint32_t lChannels = pChannels ? *pChannels : 0;
+    uint32_t lRate = pRate ? *pRate : 0;
+
     // fix up defaults
-    if (format == 0) format = AudioSystem::PCM_16_BIT;
-    if (channels == 0) channels = channelCount();
-    if (rate == 0) rate = sampleRate();
+    if (lFormat == 0) lFormat = format();
+    if (lChannels == 0) lChannels = channels();
+    if (lRate == 0) lRate = sampleRate();
 
     // check values
-    if ((format != AudioSystem::PCM_16_BIT) ||
-            (channels != channelCount()) ||
-            (rate != sampleRate()))
+    if ((lFormat != format()) ||
+            (lChannels != channels()) ||
+            (lRate != sampleRate())) {
+        if (pFormat) *pFormat = format();
+        if (pChannels) *pChannels = channels();
+        if (pRate) *pRate = sampleRate();
         return BAD_VALUE;
+    }
+
+    if (pFormat) *pFormat = lFormat;
+    if (pChannels) *pChannels = lChannels;
+    if (pRate) *pRate = lRate;
 
     mAudioHardware = hw;
     mFd = fd;
+    mDevice = devices;
     return NO_ERROR;
 }
 
 AudioStreamOutGeneric::~AudioStreamOutGeneric()
 {
-    if (mAudioHardware)
-        mAudioHardware->closeOutputStream(this);
 }
 
 ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes)
@@ -234,10 +251,12 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
     result.append(buffer);
-    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
     result.append(buffer);
     snprintf(buffer, SIZE, "\tformat: %d\n", format());
     result.append(buffer);
+    snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
+    result.append(buffer);
     snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
     result.append(buffer);
     snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
@@ -246,29 +265,68 @@
     return NO_ERROR;
 }
 
+status_t AudioStreamOutGeneric::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 key = String8(AudioParameter::keyRouting);
+    status_t status = NO_ERROR;
+    int device;
+    LOGV("setParameters() %s", keyValuePairs.string());
+
+    if (param.getInt(key, device) == NO_ERROR) {
+        mDevice = device;
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+String8 AudioStreamOutGeneric::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+    String8 key = String8(AudioParameter::keyRouting);
+
+    if (param.get(key, value) == NO_ERROR) {
+        param.addInt(key, (int)mDevice);
+    }
+
+    LOGV("getParameters() %s", param.toString().string());
+    return param.toString();
+}
+
 // ----------------------------------------------------------------------------
 
 // record functions
 status_t AudioStreamInGeneric::set(
         AudioHardwareGeneric *hw,
         int fd,
-        int format,
-        int channels,
-        uint32_t rate,
+        uint32_t devices,
+        int *pFormat,
+        uint32_t *pChannels,
+        uint32_t *pRate,
         AudioSystem::audio_in_acoustics acoustics)
 {
     // FIXME: remove logging
-    LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, format, channels, rate);
+    if (pFormat == 0 || pChannels == 0 || pRate == 0) return BAD_VALUE;
+    LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate);
     // check values
-    if ((format != AudioSystem::PCM_16_BIT) ||
-            (channels != channelCount()) ||
-            (rate != sampleRate())) {
+    if ((*pFormat != format()) ||
+        (*pChannels != channels()) ||
+        (*pRate != sampleRate())) {
         LOGE("Error opening input channel");
+        *pFormat = format();
+        *pChannels = channels();
+        *pRate = sampleRate();
         return BAD_VALUE;
     }
 
     mAudioHardware = hw;
     mFd = fd;
+    mDevice = devices;
     return NO_ERROR;
 }
 
@@ -276,14 +334,12 @@
 {
     // FIXME: remove logging
     LOGD("AudioStreamInGeneric destructor");
-    if (mAudioHardware)
-        mAudioHardware->closeInputStream(this);
 }
 
 ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes)
 {
     // FIXME: remove logging
-    LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, bytes, mFd);
+    LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, (int)bytes, mFd);
     AutoMutex lock(mLock);
     if (mFd < 0) {
         LOGE("Attempt to read from unopened device");
@@ -303,10 +359,12 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
     result.append(buffer);
-    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
     result.append(buffer);
     snprintf(buffer, SIZE, "\tformat: %d\n", format());
     result.append(buffer);
+    snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
+    result.append(buffer);
     snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
     result.append(buffer);
     snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
@@ -315,6 +373,39 @@
     return NO_ERROR;
 }
 
+status_t AudioStreamInGeneric::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 key = String8(AudioParameter::keyRouting);
+    status_t status = NO_ERROR;
+    int device;
+    LOGV("setParameters() %s", keyValuePairs.string());
+
+    if (param.getInt(key, device) == NO_ERROR) {
+        mDevice = device;
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+String8 AudioStreamInGeneric::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+    String8 key = String8(AudioParameter::keyRouting);
+
+    if (param.get(key, value) == NO_ERROR) {
+        param.addInt(key, (int)mDevice);
+    }
+
+    LOGV("getParameters() %s", param.toString().string());
+    return param.toString();
+}
+
 // ----------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h
index c89df87..42da413 100644
--- a/libs/audioflinger/AudioHardwareGeneric.h
+++ b/libs/audioflinger/AudioHardwareGeneric.h
@@ -39,24 +39,28 @@
     virtual status_t    set(
             AudioHardwareGeneric *hw,
             int mFd,
-            int format,
-            int channelCount,
-            uint32_t sampleRate);
+            uint32_t devices,
+            int *pFormat,
+            uint32_t *pChannels,
+            uint32_t *pRate);
 
     virtual uint32_t    sampleRate() const { return 44100; }
     virtual size_t      bufferSize() const { return 4096; }
-    virtual int         channelCount() const { return 2; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
     virtual int         format() const { return AudioSystem::PCM_16_BIT; }
     virtual uint32_t    latency() const { return 20; }
-    virtual status_t    setVolume(float volume) { return INVALID_OPERATION; }
+    virtual status_t    setVolume(float left, float right) { return INVALID_OPERATION; }
     virtual ssize_t     write(const void* buffer, size_t bytes);
     virtual status_t    standby();
     virtual status_t    dump(int fd, const Vector<String16>& args);
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
 
 private:
     AudioHardwareGeneric *mAudioHardware;
     Mutex   mLock;
     int     mFd;
+    uint32_t mDevice;
 };
 
 class AudioStreamInGeneric : public AudioStreamIn {
@@ -67,24 +71,28 @@
     virtual status_t    set(
             AudioHardwareGeneric *hw,
             int mFd,
-            int format,
-            int channelCount,
-            uint32_t sampleRate,
+            uint32_t devices,
+            int *pFormat,
+            uint32_t *pChannels,
+            uint32_t *pRate,
             AudioSystem::audio_in_acoustics acoustics);
 
-    uint32_t    sampleRate() const { return 8000; }
+    virtual uint32_t    sampleRate() const { return 8000; }
     virtual size_t      bufferSize() const { return 320; }
-    virtual int         channelCount() const { return 1; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_IN_MONO; }
     virtual int         format() const { return AudioSystem::PCM_16_BIT; }
     virtual status_t    setGain(float gain) { return INVALID_OPERATION; }
     virtual ssize_t     read(void* buffer, ssize_t bytes);
     virtual status_t    dump(int fd, const Vector<String16>& args);
     virtual status_t    standby() { return NO_ERROR; }
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
 
 private:
     AudioHardwareGeneric *mAudioHardware;
     Mutex   mLock;
     int     mFd;
+    uint32_t mDevice;
 };
 
 
@@ -101,28 +109,27 @@
     virtual status_t    setMicMute(bool state);
     virtual status_t    getMicMute(bool* state);
 
-    virtual status_t    setParameter(const char* key, const char* value)
-            { return NO_ERROR; }
-
     // create I/O streams
     virtual AudioStreamOut* openOutputStream(
-            int format=0,
-            int channelCount=0,
-            uint32_t sampleRate=0,
+            uint32_t devices,
+            int *format=0,
+            uint32_t *channels=0,
+            uint32_t *sampleRate=0,
             status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
 
     virtual AudioStreamIn* openInputStream(
-            int inputSource,
-            int format,
-            int channelCount,
-            uint32_t sampleRate,
+            uint32_t devices,
+            int *format,
+            uint32_t *channels,
+            uint32_t *sampleRate,
             status_t *status,
             AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
 
             void            closeOutputStream(AudioStreamOutGeneric* out);
             void            closeInputStream(AudioStreamInGeneric* in);
 protected:
-    virtual status_t        doRouting() { return NO_ERROR; }
     virtual status_t        dump(int fd, const Vector<String16>& args);
 
 private:
diff --git a/libs/audioflinger/AudioHardwareInterface.cpp b/libs/audioflinger/AudioHardwareInterface.cpp
index cc1bd8f..37be329 100644
--- a/libs/audioflinger/AudioHardwareInterface.cpp
+++ b/libs/audioflinger/AudioHardwareInterface.cpp
@@ -18,6 +18,7 @@
 #include <cutils/properties.h>
 #include <string.h>
 #include <unistd.h>
+//#define LOG_NDEBUG 0
 
 #define LOG_TAG "AudioHardwareInterface"
 #include <utils/Log.h>
@@ -25,15 +26,17 @@
 
 #include "AudioHardwareStub.h"
 #include "AudioHardwareGeneric.h"
+#ifdef WITH_A2DP
+#include "A2dpAudioInterface.h"
+#endif
 
-//#define DUMP_FLINGER_OUT        // if defined allows recording samples in a file
-#ifdef DUMP_FLINGER_OUT
+#ifdef ENABLE_AUDIO_DUMP
 #include "AudioDumpInterface.h"
 #endif
 
 
 // change to 1 to log routing calls
-#define LOG_ROUTING_CALLS 0
+#define LOG_ROUTING_CALLS 1
 
 namespace android {
 
@@ -48,14 +51,6 @@
     "IN_CALL"
 };
 
-static const char* routeStrings[] =
-{
-    "EARPIECE ",
-    "SPEAKER ",
-    "BLUETOOTH ",
-    "HEADSET ",
-    "BLUETOOTH_A2DP "
-};
 static const char* routeNone = "NONE";
 
 static const char* displayMode(int mode)
@@ -64,22 +59,6 @@
         return routingModeStrings[0];
     return routingModeStrings[mode+3];
 }
-
-static const char* displayRoutes(uint32_t routes)
-{
-    static char routeStr[80];
-    if (routes == 0)
-        return routeNone;
-    routeStr[0] = 0;
-    int bitMask = 1;
-    for (int i = 0; i < 4; ++i, bitMask <<= 1) {
-        if (routes & bitMask) {
-            strcat(routeStr, routeStrings[i]);
-        }
-    }
-    routeStr[strlen(routeStr)-1] = 0;
-    return routeStr;
-}
 #endif
 
 // ----------------------------------------------------------------------------
@@ -112,13 +91,17 @@
         hw = new AudioHardwareStub();
     }
     
-#ifdef DUMP_FLINGER_OUT
+#ifdef WITH_A2DP
+    hw = new A2dpAudioInterface(hw);
+#endif
+
+#ifdef ENABLE_AUDIO_DUMP
     // This code adds a record of buffers in a file to write calls made by AudioFlinger.
     // It replaces the current AudioHardwareInterface object by an intermediate one which
     // will record buffers in a file (after sending them to hardware) for testing purpose.
-    // This feature is enabled by defining symbol DUMP_FLINGER_OUT.
-    // The output file is FLINGER_DUMP_NAME. Pause are not recorded in the file.
-    
+    // This feature is enabled by defining symbol ENABLE_AUDIO_DUMP.
+    // The output file is set with setParameters("test_cmd_file_name=<name>"). Pause are not recorded in the file.
+    LOGV("opening PCM dump interface");
     hw = new AudioDumpInterface(hw);    // replace interface
 #endif
     return hw;
@@ -132,48 +115,9 @@
 
 AudioHardwareBase::AudioHardwareBase()
 {
-    // force a routing update on initialization
-    memset(&mRoutes, 0, sizeof(mRoutes));
     mMode = 0;
 }
 
-// generics for audio routing - the real work is done in doRouting
-status_t AudioHardwareBase::setRouting(int mode, uint32_t routes)
-{
-#if LOG_ROUTING_CALLS
-    LOGD("setRouting: mode=%s, routes=[%s]", displayMode(mode), displayRoutes(routes));
-#endif
-    if (mode == AudioSystem::MODE_CURRENT)
-        mode = mMode;
-    if ((mode < 0) || (mode >= AudioSystem::NUM_MODES))
-        return BAD_VALUE;
-    uint32_t old = mRoutes[mode];
-    mRoutes[mode] = routes;
-    if ((mode != mMode) || (old == routes))
-        return NO_ERROR;
-#if LOG_ROUTING_CALLS
-    const char* oldRouteStr = strdup(displayRoutes(old));
-    LOGD("doRouting: mode=%s, old route=[%s], new route=[%s]",
-           displayMode(mode), oldRouteStr, displayRoutes(routes));
-    delete oldRouteStr;
-#endif
-    return doRouting();
-}
-
-status_t AudioHardwareBase::getRouting(int mode, uint32_t* routes)
-{
-    if (mode == AudioSystem::MODE_CURRENT)
-        mode = mMode;
-    if ((mode < 0) || (mode >= AudioSystem::NUM_MODES))
-        return BAD_VALUE;
-    *routes = mRoutes[mode];
-#if LOG_ROUTING_CALLS
-    LOGD("getRouting: mode=%s, routes=[%s]",
-           displayMode(mode), displayRoutes(*routes));
-#endif
-    return NO_ERROR;
-}
-
 status_t AudioHardwareBase::setMode(int mode)
 {
 #if LOG_ROUTING_CALLS
@@ -182,28 +126,23 @@
     if ((mode < 0) || (mode >= AudioSystem::NUM_MODES))
         return BAD_VALUE;
     if (mMode == mode)
-        return NO_ERROR;
-#if LOG_ROUTING_CALLS
-    LOGD("doRouting: old mode=%s, new mode=%s route=[%s]",
-            displayMode(mMode), displayMode(mode), displayRoutes(mRoutes[mode]));
-#endif
+        return ALREADY_EXISTS;
     mMode = mode;
-    return doRouting();
-}
-
-status_t AudioHardwareBase::getMode(int* mode)
-{
-    // Implement: set audio routing
-    *mode = mMode;
     return NO_ERROR;
 }
 
-status_t AudioHardwareBase::setParameter(const char* key, const char* value)
+// default implementation
+status_t AudioHardwareBase::setParameters(const String8& keyValuePairs)
 {
-    // default implementation is to ignore
     return NO_ERROR;
 }
 
+// default implementation
+String8 AudioHardwareBase::getParameters(const String8& keys)
+{
+    String8 result = String8("");
+    return result;
+}
 
 // default implementation
 size_t AudioHardwareBase::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
@@ -233,10 +172,6 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "\tmMode: %d\n", mMode);
     result.append(buffer);
-    for (int i = 0, n = AudioSystem::NUM_MODES; i < n; ++i) {
-        snprintf(buffer, SIZE, "\tmRoutes[%d]: %d\n", i, mRoutes[i]);
-        result.append(buffer);
-    }
     ::write(fd, result.string(), result.size());
     dump(fd, args);  // Dump the state of the concrete child.
     return NO_ERROR;
diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp
index 0ab4c60..1a03059 100644
--- a/libs/audioflinger/AudioHardwareStub.cpp
+++ b/libs/audioflinger/AudioHardwareStub.cpp
@@ -43,10 +43,10 @@
 }
 
 AudioStreamOut* AudioHardwareStub::openOutputStream(
-        int format, int channelCount, uint32_t sampleRate, status_t *status)
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
 {
     AudioStreamOutStub* out = new AudioStreamOutStub();
-    status_t lStatus = out->set(format, channelCount, sampleRate);
+    status_t lStatus = out->set(format, channels, sampleRate);
     if (status) {
         *status = lStatus;
     }
@@ -56,18 +56,22 @@
     return 0;
 }
 
+void AudioHardwareStub::closeOutputStream(AudioStreamOut* out)
+{
+    delete out;
+}
+
 AudioStreamIn* AudioHardwareStub::openInputStream(
-        int inputSource, int format, int channelCount, uint32_t sampleRate,
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
         status_t *status, AudioSystem::audio_in_acoustics acoustics)
 {
     // check for valid input source
-    if ((inputSource < AudioRecord::DEFAULT_INPUT) ||
-        (inputSource >= AudioRecord::NUM_INPUT_SOURCES)) {
+    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
         return 0;
     }
 
     AudioStreamInStub* in = new AudioStreamInStub();
-    status_t lStatus = in->set(format, channelCount, sampleRate, acoustics);
+    status_t lStatus = in->set(format, channels, sampleRate, acoustics);
     if (status) {
         *status = lStatus;
     }
@@ -77,6 +81,11 @@
     return 0;
 }
 
+void AudioHardwareStub::closeInputStream(AudioStreamIn* in)
+{
+    delete in;
+}
+
 status_t AudioHardwareStub::setVoiceVolume(float volume)
 {
     return NO_ERROR;
@@ -107,24 +116,19 @@
 
 // ----------------------------------------------------------------------------
 
-status_t AudioStreamOutStub::set(int format, int channels, uint32_t rate)
+status_t AudioStreamOutStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate)
 {
-    // fix up defaults
-    if (format == 0) format = AudioSystem::PCM_16_BIT;
-    if (channels == 0) channels = channelCount();
-    if (rate == 0) rate = sampleRate();
+    if (pFormat) *pFormat = format();
+    if (pChannels) *pChannels = channels();
+    if (pRate) *pRate = sampleRate();
 
-    if ((format == AudioSystem::PCM_16_BIT) &&
-            (channels == channelCount()) &&
-            (rate == sampleRate()))
-        return NO_ERROR;
-    return BAD_VALUE;
+    return NO_ERROR;
 }
 
 ssize_t AudioStreamOutStub::write(const void* buffer, size_t bytes)
 {
     // fake timing for audio output
-    usleep(bytes * 1000000 / sizeof(int16_t) / channelCount() / sampleRate());
+    usleep(bytes * 1000000 / sizeof(int16_t) / AudioSystem::popCount(channels()) / sampleRate());
     return bytes;
 }
 
@@ -141,7 +145,7 @@
     snprintf(buffer, SIZE, "AudioStreamOutStub::dump\n");
     snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
     snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
-    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
     snprintf(buffer, SIZE, "\tformat: %d\n", format());
     result.append(buffer);
     ::write(fd, result.string(), result.size());
@@ -150,20 +154,16 @@
 
 // ----------------------------------------------------------------------------
 
-status_t AudioStreamInStub::set(int format, int channels, uint32_t rate,
+status_t AudioStreamInStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate,
 				AudioSystem::audio_in_acoustics acoustics)
 {
-    if ((format == AudioSystem::PCM_16_BIT) &&
-            (channels == channelCount()) &&
-            (rate == sampleRate()))
-        return NO_ERROR;
-    return BAD_VALUE;
+    return NO_ERROR;
 }
 
 ssize_t AudioStreamInStub::read(void* buffer, ssize_t bytes)
 {
     // fake timing for audio input
-    usleep(bytes * 1000000 / sizeof(int16_t) / channelCount() / sampleRate());
+    usleep(bytes * 1000000 / sizeof(int16_t) / AudioSystem::popCount(channels()) / sampleRate());
     memset(buffer, 0, bytes);
     return bytes;
 }
@@ -179,7 +179,7 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
     result.append(buffer);
-    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
     result.append(buffer);
     snprintf(buffer, SIZE, "\tformat: %d\n", format());
     result.append(buffer);
diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h
index bf63cc5..8f43259 100644
--- a/libs/audioflinger/AudioHardwareStub.h
+++ b/libs/audioflinger/AudioHardwareStub.h
@@ -29,29 +29,33 @@
 
 class AudioStreamOutStub : public AudioStreamOut {
 public:
-    virtual status_t    set(int format, int channelCount, uint32_t sampleRate);
+    virtual status_t    set(int *pFormat, uint32_t *pChannels, uint32_t *pRate);
     virtual uint32_t    sampleRate() const { return 44100; }
     virtual size_t      bufferSize() const { return 4096; }
-    virtual int         channelCount() const { return 2; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
     virtual int         format() const { return AudioSystem::PCM_16_BIT; }
     virtual uint32_t    latency() const { return 0; }
-    virtual status_t    setVolume(float volume) { return NO_ERROR; }
+    virtual status_t    setVolume(float left, float right) { return NO_ERROR; }
     virtual ssize_t     write(const void* buffer, size_t bytes);
     virtual status_t    standby();
     virtual status_t    dump(int fd, const Vector<String16>& args);
+    virtual status_t    setParameters(const String8& keyValuePairs) { return NO_ERROR;}
+    virtual String8     getParameters(const String8& keys) {String8 result = String8(""); return result;}
 };
 
 class AudioStreamInStub : public AudioStreamIn {
 public:
-    virtual status_t    set(int format, int channelCount, uint32_t sampleRate, AudioSystem::audio_in_acoustics acoustics);
+    virtual status_t    set(int *pFormat, uint32_t *pChannels, uint32_t *pRate, AudioSystem::audio_in_acoustics acoustics);
     virtual uint32_t    sampleRate() const { return 8000; }
     virtual size_t      bufferSize() const { return 320; }
-    virtual int         channelCount() const { return 1; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_IN_MONO; }
     virtual int         format() const { return AudioSystem::PCM_16_BIT; }
     virtual status_t    setGain(float gain) { return NO_ERROR; }
     virtual ssize_t     read(void* buffer, ssize_t bytes);
     virtual status_t    dump(int fd, const Vector<String16>& args);
     virtual status_t    standby() { return NO_ERROR; }
+    virtual status_t    setParameters(const String8& keyValuePairs) { return NO_ERROR;}
+    virtual String8     getParameters(const String8& keys) {String8 result = String8(""); return result;}
 };
 
 class AudioHardwareStub : public  AudioHardwareBase
@@ -67,26 +71,25 @@
     virtual status_t    setMicMute(bool state) { mMicMute = state;  return  NO_ERROR; }
     virtual status_t    getMicMute(bool* state) { *state = mMicMute ; return NO_ERROR; }
 
-    virtual status_t    setParameter(const char* key, const char* value)
-            { return NO_ERROR; }
-
     // create I/O streams
     virtual AudioStreamOut* openOutputStream(
-                                int format=0,
-                                int channelCount=0,
-                                uint32_t sampleRate=0,
+                                uint32_t devices,
+                                int *format=0,
+                                uint32_t *channels=0,
+                                uint32_t *sampleRate=0,
                                 status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
 
     virtual AudioStreamIn* openInputStream(
-                                int inputSource,
-                                int format,
-                                int channelCount,
-                                uint32_t sampleRate,
+                                uint32_t devices,
+                                int *format,
+                                uint32_t *channels,
+                                uint32_t *sampleRate,
                                 status_t *status,
-				AudioSystem::audio_in_acoustics acoustics);
+                                AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
 
 protected:
-    virtual status_t    doRouting() { return NO_ERROR; }
     virtual status_t    dump(int fd, const Vector<String16>& args);
 
             bool        mMicMute;
diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp
index b02efcc..19a442a8 100644
--- a/libs/audioflinger/AudioMixer.cpp
+++ b/libs/audioflinger/AudioMixer.cpp
@@ -610,7 +610,6 @@
     t->in = in;
 }
 
-inline
 void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)
 {
     for (size_t i=0 ; i<c ; i++) {
diff --git a/libs/audioflinger/AudioMixer.h b/libs/audioflinger/AudioMixer.h
index 72ca28a..15766cd 100644
--- a/libs/audioflinger/AudioMixer.h
+++ b/libs/audioflinger/AudioMixer.h
@@ -85,6 +85,8 @@
 
     uint32_t    trackNames() const { return mTrackNames; }
 
+    static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c);
+
 private:
 
     enum {
@@ -176,7 +178,6 @@
     static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp);
     static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp);
     static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp);
-    static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c);
 
     static void process__validate(state_t* state, void* output);
     static void process__nop(state_t* state, void* output);
diff --git a/libs/audioflinger/AudioPolicyManagerGeneric.cpp b/libs/audioflinger/AudioPolicyManagerGeneric.cpp
new file mode 100644
index 0000000..4b31815
--- /dev/null
+++ b/libs/audioflinger/AudioPolicyManagerGeneric.cpp
@@ -0,0 +1,753 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#define LOG_TAG "AudioPolicyManagerGeneric"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include "AudioPolicyManagerGeneric.h"
+#include <media/mediarecorder.h>
+
+namespace android {
+
+
+// ----------------------------------------------------------------------------
+// AudioPolicyInterface implementation
+// ----------------------------------------------------------------------------
+
+
+status_t AudioPolicyManagerGeneric::setDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  AudioSystem::device_connection_state state,
+                                                  const char *device_address)
+{
+
+    LOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
+
+    // connect/disconnect only 1 device at a time
+    if (AudioSystem::popCount(device) != 1) return BAD_VALUE;
+
+    if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {
+        LOGE("setDeviceConnectionState() invalid address: %s", device_address);
+        return BAD_VALUE;
+    }
+
+    // handle output devices
+    if (AudioSystem::isOutputDevice(device)) {
+        switch (state)
+        {
+        // handle output device connection
+        case AudioSystem::DEVICE_STATE_AVAILABLE:
+            if (mAvailableOutputDevices & device) {
+                LOGW("setDeviceConnectionState() device already connected: %x", device);
+                return INVALID_OPERATION;
+            }
+            LOGV("setDeviceConnectionState() connecting device %x", device);
+
+            // register new device as available
+            mAvailableOutputDevices |= device;
+            break;
+        // handle output device disconnection
+        case AudioSystem::DEVICE_STATE_UNAVAILABLE:
+            if (!(mAvailableOutputDevices & device)) {
+                LOGW("setDeviceConnectionState() device not connected: %x", device);
+                return INVALID_OPERATION;
+            }
+            LOGV("setDeviceConnectionState() disconnecting device %x", device);
+            // remove device from available output devices
+            mAvailableOutputDevices &= ~device;
+            break;
+
+        default:
+            LOGE("setDeviceConnectionState() invalid state: %x", state);
+            return BAD_VALUE;
+        }
+        return NO_ERROR;
+    }
+    // handle input devices
+    if (AudioSystem::isInputDevice(device)) {
+        switch (state)
+        {
+        // handle input device connection
+        case AudioSystem::DEVICE_STATE_AVAILABLE:
+            if (mAvailableInputDevices & device) {
+                LOGW("setDeviceConnectionState() device already connected: %d", device);
+                return INVALID_OPERATION;
+            }
+            mAvailableInputDevices |= device;
+            break;
+
+        // handle input device disconnection
+        case AudioSystem::DEVICE_STATE_UNAVAILABLE:
+            if (!(mAvailableInputDevices & device)) {
+                LOGW("setDeviceConnectionState() device not connected: %d", device);
+                return INVALID_OPERATION;
+            }
+            mAvailableInputDevices &= ~device;
+            break;
+
+        default:
+            LOGE("setDeviceConnectionState() invalid state: %x", state);
+            return BAD_VALUE;
+        }
+        return NO_ERROR;
+    }
+
+    LOGW("setDeviceConnectionState() invalid device: %x", device);
+    return BAD_VALUE;
+}
+
+AudioSystem::device_connection_state AudioPolicyManagerGeneric::getDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  const char *device_address)
+{
+    AudioSystem::device_connection_state state = AudioSystem::DEVICE_STATE_UNAVAILABLE;
+    String8 address = String8(device_address);
+    if (AudioSystem::isOutputDevice(device)) {
+        if (device & mAvailableOutputDevices) {
+            state = AudioSystem::DEVICE_STATE_AVAILABLE;
+        }
+    } else if (AudioSystem::isInputDevice(device)) {
+        if (device & mAvailableInputDevices) {
+            state = AudioSystem::DEVICE_STATE_AVAILABLE;
+        }
+    }
+
+    return state;
+}
+
+void AudioPolicyManagerGeneric::setPhoneState(int state)
+{
+    LOGV("setPhoneState() state %d", state);
+    uint32_t newDevice = 0;
+    if (state < 0 || state >= AudioSystem::NUM_MODES) {
+        LOGW("setPhoneState() invalid state %d", state);
+        return;
+    }
+
+    if (state == mPhoneState ) {
+        LOGW("setPhoneState() setting same state %d", state);
+        return;
+    }
+    // store previous phone state for management of sonification strategy below
+    int oldState = mPhoneState;
+    mPhoneState = state;
+
+    // if leaving or entering in call state, handle special case of active streams
+    // pertaining to sonification strategy see handleIncallSonification()
+    if (state == AudioSystem::MODE_IN_CALL ||
+        oldState == AudioSystem::MODE_IN_CALL) {
+        bool starting = (state == AudioSystem::MODE_IN_CALL) ? true : false;
+        LOGV("setPhoneState() in call state management: new state is %d", state);
+        for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
+            handleIncallSonification(stream, starting);
+        }
+    }
+}
+
+void AudioPolicyManagerGeneric::setRingerMode(uint32_t mode, uint32_t mask)
+{
+    LOGV("setRingerMode() mode %x, mask %x", mode, mask);
+
+    mRingerMode = mode;
+}
+
+void AudioPolicyManagerGeneric::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+{
+    LOGV("setForceUse) usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
+    mForceUse[usage] = config;
+}
+
+AudioSystem::forced_config AudioPolicyManagerGeneric::getForceUse(AudioSystem::force_use usage)
+{
+    return mForceUse[usage];
+}
+
+void AudioPolicyManagerGeneric::setSystemProperty(const char* property, const char* value)
+{
+    LOGV("setSystemProperty() property %s, value %s", property, value);
+    if (strcmp(property, "ro.camera.sound.forced") == 0) {
+        if (atoi(value)) {
+            LOGV("ENFORCED_AUDIBLE cannot be muted");
+            mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = false;
+        } else {
+            LOGV("ENFORCED_AUDIBLE can be muted");
+            mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = true;
+        }
+    }
+}
+
+audio_io_handle_t AudioPolicyManagerGeneric::getOutput(AudioSystem::stream_type stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::output_flags flags)
+{
+    LOGV("getOutput() stream %d, samplingRate %d, format %d, channels %x, flags %x", stream, samplingRate, format, channels, flags);
+
+#ifdef AUDIO_POLICY_TEST
+    if (mCurOutput != 0) {
+        LOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channelcount %d, mDirectOutput %d",
+                mCurOutput, mTestSamplingRate, mTestFormat, mTestChannelcount, mDirectOutput);
+
+        if (mTestOutputs[mCurOutput] == 0) {
+            LOGV("getOutput() opening test output");
+            AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
+            outputDesc->mDevice = mTestDevice;
+            outputDesc->mSamplingRate = mTestSamplingRate;
+            outputDesc->mFormat = mTestFormat;
+            outputDesc->mChannels = (mTestChannelcount == 1) ? AudioSystem::CHANNEL_OUT_MONO : AudioSystem::CHANNEL_OUT_STEREO;
+            outputDesc->mLatency = mTestLatencyMs;
+            outputDesc->mFlags = (AudioSystem::output_flags)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0);
+            outputDesc->mRefCount[stream] = 0;
+            mTestOutputs[mCurOutput] = mpClientInterface->openOutput(&outputDesc->mDevice,
+                                            &outputDesc->mSamplingRate,
+                                            &outputDesc->mFormat,
+                                            &outputDesc->mChannels,
+                                            &outputDesc->mLatency,
+                                            outputDesc->mFlags);
+            mOutputs.add(mTestOutputs[mCurOutput], outputDesc);
+        }
+        return mTestOutputs[mCurOutput];
+    }
+#endif //AUDIO_POLICY_TEST
+    if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
+        (format != 0 && !AudioSystem::isLinearPCM(format)) ||
+        (channels != 0 && channels != AudioSystem::CHANNEL_OUT_MONO && channels != AudioSystem::CHANNEL_OUT_STEREO)) {
+        return NULL;
+    }
+
+    return mHardwareOutput;
+}
+
+status_t AudioPolicyManagerGeneric::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    LOGV("startOutput() output %p, stream %d", output, stream);
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        LOGW("startOutput() unknow output %p", output);
+        return BAD_VALUE;
+    }
+
+    AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
+
+    // handle special case for sonification while in call
+    if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+        handleIncallSonification(stream, true);
+    }
+
+    // incremenent usage count for this stream on the requested output:
+    outputDesc->changeRefCount(stream, 1);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerGeneric::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    LOGV("stopOutput() output %p, stream %d", output, stream);
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        LOGW("stopOutput() unknow output %p", output);
+        return BAD_VALUE;
+    }
+
+    AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
+
+    // handle special case for sonification while in call
+    if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+        handleIncallSonification(stream, false);
+    }
+
+    if (outputDesc->isUsedByStream(stream)) {
+        // decrement usage count of this stream on the output
+        outputDesc->changeRefCount(stream, -1);
+        return NO_ERROR;
+    } else {
+        LOGW("stopOutput() refcount is already 0 for output %p", output);
+        return INVALID_OPERATION;
+    }
+}
+
+void AudioPolicyManagerGeneric::releaseOutput(audio_io_handle_t output)
+{
+    LOGV("releaseOutput() %p", output);
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        LOGW("releaseOutput() releasing unknown output %p", output);
+        return;
+    }
+
+#ifdef AUDIO_POLICY_TEST
+    int testIndex = testOutputIndex(output);
+    if (testIndex != 0) {
+        AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
+        if (outputDesc->refCount() == 0) {
+            mpClientInterface->closeOutput(output);
+            delete mOutputs.valueAt(index);
+            mOutputs.removeItem(output);
+            mTestOutputs[testIndex] = 0;
+        }
+    }
+#endif //AUDIO_POLICY_TEST
+}
+
+audio_io_handle_t AudioPolicyManagerGeneric::getInput(int inputSource,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::audio_in_acoustics acoustics)
+{
+    audio_io_handle_t input = 0;
+    uint32_t device;
+
+    LOGV("getInput() inputSource %d, samplingRate %d, format %d, channels %x, acoustics %x", inputSource, samplingRate, format, channels, acoustics);
+
+    AudioInputDescriptor *inputDesc = new AudioInputDescriptor();
+    inputDesc->mDevice = AudioSystem::DEVICE_IN_BUILTIN_MIC;
+    inputDesc->mSamplingRate = samplingRate;
+    inputDesc->mFormat = format;
+    inputDesc->mChannels = channels;
+    inputDesc->mAcoustics = acoustics;
+    inputDesc->mRefCount = 0;
+    input = mpClientInterface->openInput(&inputDesc->mDevice,
+                                    &inputDesc->mSamplingRate,
+                                    &inputDesc->mFormat,
+                                    &inputDesc->mChannels,
+                                    inputDesc->mAcoustics);
+
+    // only accept input with the exact requested set of parameters
+    if ((samplingRate != inputDesc->mSamplingRate) ||
+        (format != inputDesc->mFormat) ||
+        (channels != inputDesc->mChannels)) {
+        LOGV("getOutput() failed opening input: samplingRate %d, format %d, channels %d",
+                samplingRate, format, channels);
+        mpClientInterface->closeInput(input);
+        delete inputDesc;
+        return NULL;
+    }
+    mInputs.add(input, inputDesc);
+    return input;
+}
+
+status_t AudioPolicyManagerGeneric::startInput(audio_io_handle_t input)
+{
+    LOGV("startInput() input %p", input);
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        LOGW("startInput() unknow input %p", input);
+        return BAD_VALUE;
+    }
+    AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
+
+#ifdef AUDIO_POLICY_TEST
+    if (mTestInput == 0)
+#endif //AUDIO_POLICY_TEST
+    {
+        // refuse 2 active AudioRecord clients at the same time
+        for (size_t i = 0; i < mInputs.size(); i++) {
+            if (mInputs.valueAt(i)->mRefCount > 0) {
+                LOGW("startInput() input %p, other input %p already started", input, mInputs.keyAt(i));
+                return INVALID_OPERATION;
+            }
+        }
+    }
+
+    inputDesc->mRefCount = 1;
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerGeneric::stopInput(audio_io_handle_t input)
+{
+    LOGV("stopInput() input %p", input);
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        LOGW("stopInput() unknow input %p", input);
+        return BAD_VALUE;
+    }
+    AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
+
+    if (inputDesc->mRefCount == 0) {
+        LOGW("stopInput() input %p already stopped", input);
+        return INVALID_OPERATION;
+    } else {
+        inputDesc->mRefCount = 0;
+        return NO_ERROR;
+    }
+}
+
+void AudioPolicyManagerGeneric::releaseInput(audio_io_handle_t input)
+{
+    LOGV("releaseInput() %p", input);
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        LOGW("releaseInput() releasing unknown input %p", input);
+        return;
+    }
+    mpClientInterface->closeInput(input);
+    delete mInputs.valueAt(index);
+    mInputs.removeItem(input);
+}
+
+
+
+void AudioPolicyManagerGeneric::initStreamVolume(AudioSystem::stream_type stream,
+                                            int indexMin,
+                                            int indexMax)
+{
+    LOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
+    mStreams[stream].mIndexMin = indexMin;
+    mStreams[stream].mIndexMax = indexMax;
+}
+
+status_t AudioPolicyManagerGeneric::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+{
+
+    if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
+        return BAD_VALUE;
+    }
+
+    LOGV("setStreamVolumeIndex() stream %d, index %d", stream, index);
+    mStreams[stream].mIndexCur = index;
+
+    // do not change actual stream volume if the stream is muted
+    if (mStreams[stream].mMuteCount != 0) {
+        return NO_ERROR;
+    }
+
+    // Do not changed in call volume if bluetooth is connected and vice versa
+    if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||
+        (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) {
+        LOGV("setStreamVolumeIndex() cannot set stream %d volume with force use = %d for comm",
+             stream, mForceUse[AudioSystem::FOR_COMMUNICATION]);
+        return INVALID_OPERATION;
+    }
+
+    // compute and apply stream volume on all outputs according to connected device
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i);
+        uint32_t device = outputDesc->device();
+
+        float volume = computeVolume((int)stream, index, device);
+
+        LOGV("setStreamVolume() for output %p stream %d, volume %f", mOutputs.keyAt(i), stream, volume);
+        mpClientInterface->setStreamVolume(stream, volume, mOutputs.keyAt(i));
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerGeneric::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+{
+    if (index == 0) {
+        return BAD_VALUE;
+    }
+    LOGV("getStreamVolumeIndex() stream %d", stream);
+    *index =  mStreams[stream].mIndexCur;
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+// AudioPolicyManagerGeneric
+// ----------------------------------------------------------------------------
+
+// ---  class factory
+
+AudioPolicyManagerGeneric::AudioPolicyManagerGeneric(AudioPolicyClientInterface *clientInterface)
+    :
+#ifdef AUDIO_POLICY_TEST
+    Thread(false),
+#endif //AUDIO_POLICY_TEST
+    mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0)
+{
+    mpClientInterface = clientInterface;
+
+    for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
+        mForceUse[i] = AudioSystem::FORCE_NONE;
+    }
+
+    // devices available by default are speaker, ear piece and microphone
+    mAvailableOutputDevices = AudioSystem::DEVICE_OUT_SPEAKER;
+    mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
+
+    // open hardware output
+    AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
+    outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
+    mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
+                                    &outputDesc->mSamplingRate,
+                                    &outputDesc->mFormat,
+                                    &outputDesc->mChannels,
+                                    &outputDesc->mLatency,
+                                    outputDesc->mFlags);
+
+    if (mHardwareOutput == 0) {
+        LOGE("Failed to initialize hardware output stream, samplingRate: %d, format %d, channels %d",
+                outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
+    } else {
+        mOutputs.add(mHardwareOutput, outputDesc);
+    }
+
+#ifdef AUDIO_POLICY_TEST
+    mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER;
+    mTestSamplingRate = 44100;
+    mTestFormat = AudioSystem::PCM_16_BIT;
+    mTestChannelcount = 2;
+    mTestLatencyMs = 0;
+    mCurOutput = 0;
+    mDirectOutput = false;
+    for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
+        mTestOutputs[i] = 0;
+    }
+
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    snprintf(buffer, SIZE, "AudioPolicyManagerTest");
+    run(buffer, ANDROID_PRIORITY_AUDIO);
+#endif //AUDIO_POLICY_TEST
+}
+
+AudioPolicyManagerGeneric::~AudioPolicyManagerGeneric()
+{
+#ifdef AUDIO_POLICY_TEST
+    exit();
+#endif //AUDIO_POLICY_TEST
+
+   for (size_t i = 0; i < mOutputs.size(); i++) {
+        mpClientInterface->closeOutput(mOutputs.keyAt(i));
+        delete mOutputs.valueAt(i);
+   }
+   mOutputs.clear();
+   for (size_t i = 0; i < mInputs.size(); i++) {
+        mpClientInterface->closeInput(mInputs.keyAt(i));
+        delete mInputs.valueAt(i);
+   }
+   mInputs.clear();
+}
+
+#ifdef AUDIO_POLICY_TEST
+bool AudioPolicyManagerGeneric::threadLoop()
+{
+    LOGV("entering threadLoop()");
+    while (!exitPending())
+    {
+        Mutex::Autolock _l(mLock);
+        mWaitWorkCV.waitRelative(mLock, milliseconds(50));
+        String8 command;
+        command = mpClientInterface->getParameters(0, String8("test_cmd_policy"));
+        if (command != "") {
+            LOGV("Test command %s received", command.string());
+            AudioParameter param = AudioParameter(command);
+            int valueInt;
+            String8 value;
+            if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_output"));
+                mCurOutput = valueInt;
+            }
+            if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_direct"));
+                if (value == "false") {
+                    mDirectOutput = false;
+                } else if (value == "true") {
+                    mDirectOutput = true;
+                }
+            }
+            if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_input"));
+                mTestInput = valueInt;
+            }
+
+            if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_format"));
+                if (value == "PCM 16 bits") {
+                    mTestFormat = AudioSystem::PCM_16_BIT;
+                } else if (value == "PCM 8 bits") {
+                    mTestFormat = AudioSystem::PCM_8_BIT;
+                } else if (value == "Compressed MP3") {
+                    mTestFormat = AudioSystem::MP3;
+                }
+            }
+            if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_channels"));
+                if (value == "Channels Stereo") {
+                    mTestChannelcount = 2;
+                } else if (value == "Channels Mono") {
+                    mTestChannelcount = 1;
+                }
+            }
+            if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_sampleRate"));
+                if (valueInt >= 0 && valueInt <= 96000) {
+                    mTestSamplingRate = valueInt;
+                }
+            }
+            mpClientInterface->setParameters(0, String8("test_cmd_policy="));
+        }
+    }
+    return false;
+}
+
+void AudioPolicyManagerGeneric::exit()
+{
+    {
+        AutoMutex _l(mLock);
+        requestExit();
+        mWaitWorkCV.signal();
+    }
+    requestExitAndWait();
+}
+
+int AudioPolicyManagerGeneric::testOutputIndex(audio_io_handle_t output)
+{
+    for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
+        if (output == mTestOutputs[i]) return i;
+    }
+    return 0;
+}
+#endif //AUDIO_POLICY_TEST
+
+// ---
+
+AudioPolicyManagerGeneric::routing_strategy AudioPolicyManagerGeneric::getStrategy(AudioSystem::stream_type stream)
+{
+    // stream to strategy mapping
+    switch (stream) {
+    case AudioSystem::VOICE_CALL:
+    case AudioSystem::BLUETOOTH_SCO:
+        return STRATEGY_PHONE;
+    case AudioSystem::RING:
+    case AudioSystem::NOTIFICATION:
+    case AudioSystem::ALARM:
+    case AudioSystem::ENFORCED_AUDIBLE:
+        return STRATEGY_SONIFICATION;
+    case AudioSystem::DTMF:
+        return STRATEGY_DTMF;
+    default:
+        LOGE("unknown stream type");
+    case AudioSystem::SYSTEM:
+        // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
+        // while key clicks are played produces a poor result
+    case AudioSystem::TTS:
+    case AudioSystem::MUSIC:
+        return STRATEGY_MEDIA;
+    }
+}
+
+
+float AudioPolicyManagerGeneric::computeVolume(int stream, int index, uint32_t device)
+{
+    float volume = 1.0;
+
+    StreamDescriptor &streamDesc = mStreams[stream];
+
+    // Force max volume if stream cannot be muted
+    if (!streamDesc.mCanBeMuted) index = streamDesc.mIndexMax;
+
+    int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin);
+    volume = AudioSystem::linearToLog(volInt);
+
+    return volume;
+}
+
+void AudioPolicyManagerGeneric::setStreamMute(int stream, bool on, audio_io_handle_t output)
+{
+    LOGV("setStreamMute() stream %d, mute %d, output %p", stream, on, output);
+
+    StreamDescriptor &streamDesc = mStreams[stream];
+
+    if (on) {
+        if (streamDesc.mMuteCount++ == 0) {
+            if (streamDesc.mCanBeMuted) {
+                mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, 0, output);
+            }
+        }
+    } else {
+        if (streamDesc.mMuteCount == 0) {
+            LOGW("setStreamMute() unmuting non muted stream!");
+            return;
+        }
+        if (--streamDesc.mMuteCount == 0) {
+            uint32_t device = mOutputs.valueFor(output)->mDevice;
+            float volume = computeVolume(stream, streamDesc.mIndexCur, device);
+            mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output);
+        }
+    }
+}
+
+void AudioPolicyManagerGeneric::handleIncallSonification(int stream, bool starting)
+{
+    // if the stream pertains to sonification strategy and we are in call we must
+    // mute the stream if it is low visibility. If it is high visibility, we must play a tone
+    // in the device used for phone strategy and play the tone if the selected device does not
+    // interfere with the device used for phone strategy
+    if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) {
+        AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput);
+        LOGV("handleIncallSonification() stream %d starting %d device %x", stream, starting, outputDesc->mDevice);
+        if (outputDesc->isUsedByStream((AudioSystem::stream_type)stream)) {
+            if (AudioSystem::isLowVisibility((AudioSystem::stream_type)stream)) {
+                LOGV("handleIncallSonification() low visibility");
+                setStreamMute(stream, starting, mHardwareOutput);
+            } else {
+                if (starting) {
+                    mpClientInterface->startTone(ToneGenerator::TONE_SUP_CALL_WAITING, AudioSystem::VOICE_CALL);
+                } else {
+                    mpClientInterface->stopTone();
+                }
+            }
+        }
+    }
+}
+
+
+// --- AudioOutputDescriptor class implementation
+
+AudioPolicyManagerGeneric::AudioOutputDescriptor::AudioOutputDescriptor()
+    : mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0),
+    mFlags((AudioSystem::output_flags)0), mDevice(0)
+{
+    // clear usage count for all stream types
+    for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+        mRefCount[i] = 0;
+    }
+}
+
+uint32_t AudioPolicyManagerGeneric::AudioOutputDescriptor::device()
+{
+    return mDevice;
+}
+
+void AudioPolicyManagerGeneric::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta)
+{
+    if ((delta + (int)mRefCount[stream]) < 0) {
+        LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]);
+        mRefCount[stream] = 0;
+        return;
+    }
+    mRefCount[stream] += delta;
+    LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
+}
+
+uint32_t AudioPolicyManagerGeneric::AudioOutputDescriptor::refCount()
+{
+    uint32_t refcount = 0;
+    for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+        refcount += mRefCount[i];
+    }
+    return refcount;
+}
+
+// --- AudioInputDescriptor class implementation
+
+AudioPolicyManagerGeneric::AudioInputDescriptor::AudioInputDescriptor()
+    : mSamplingRate(0), mFormat(0), mChannels(0),
+     mAcoustics((AudioSystem::audio_in_acoustics)0), mDevice(0), mRefCount(0)
+{
+}
+
+}; // namespace android
diff --git a/libs/audioflinger/AudioPolicyManagerGeneric.h b/libs/audioflinger/AudioPolicyManagerGeneric.h
new file mode 100644
index 0000000..ddcb306
--- /dev/null
+++ b/libs/audioflinger/AudioPolicyManagerGeneric.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2009 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 <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <hardware_legacy/AudioPolicyInterface.h>
+#include <utils/threads.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+#define MAX_DEVICE_ADDRESS_LEN 20
+#define NUM_TEST_OUTPUTS 5
+
+class AudioPolicyManagerGeneric: public AudioPolicyInterface
+#ifdef AUDIO_POLICY_TEST
+    , public Thread
+#endif //AUDIO_POLICY_TEST
+{
+
+public:
+                AudioPolicyManagerGeneric(AudioPolicyClientInterface *clientInterface);
+        virtual ~AudioPolicyManagerGeneric();
+
+        // AudioPolicyInterface
+        virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
+                                                          AudioSystem::device_connection_state state,
+                                                          const char *device_address);
+        virtual AudioSystem::device_connection_state getDeviceConnectionState(AudioSystem::audio_devices device,
+                                                                              const char *device_address);
+        virtual void setPhoneState(int state);
+        virtual void setRingerMode(uint32_t mode, uint32_t mask);
+        virtual void setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config);
+        virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage);
+        virtual void setSystemProperty(const char* property, const char* value);
+        virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream,
+                                            uint32_t samplingRate,
+                                            uint32_t format,
+                                            uint32_t channels,
+                                            AudioSystem::output_flags flags);
+        virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+        virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+        virtual void releaseOutput(audio_io_handle_t output);
+        virtual audio_io_handle_t getInput(int inputSource,
+                                            uint32_t samplingRate,
+                                            uint32_t format,
+                                            uint32_t channels,
+                                            AudioSystem::audio_in_acoustics acoustics);
+        // indicates to the audio policy manager that the input starts being used.
+        virtual status_t startInput(audio_io_handle_t input);
+        // indicates to the audio policy manager that the input stops being used.
+        virtual status_t stopInput(audio_io_handle_t input);
+        virtual void releaseInput(audio_io_handle_t input);
+        virtual void initStreamVolume(AudioSystem::stream_type stream,
+                                                    int indexMin,
+                                                    int indexMax);
+        virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index);
+        virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
+
+private:
+
+        enum routing_strategy {
+            STRATEGY_MEDIA,
+            STRATEGY_PHONE,
+            STRATEGY_SONIFICATION,
+            STRATEGY_DTMF,
+            NUM_STRATEGIES
+        };
+
+        // descriptor for audio outputs. Used to maintain current configuration of each opened audio output
+        // and keep track of the usage of this output by each audio stream type.
+        class AudioOutputDescriptor
+        {
+        public:
+            AudioOutputDescriptor();
+
+
+            uint32_t device();
+            void changeRefCount(AudioSystem::stream_type, int delta);
+            bool isUsedByStream(AudioSystem::stream_type stream) { return mRefCount[stream] > 0 ? true : false; }
+            uint32_t refCount();
+
+            uint32_t mSamplingRate;             //
+            uint32_t mFormat;                   //
+            uint32_t mChannels;                 // output configuration
+            uint32_t mLatency;                  //
+            AudioSystem::output_flags mFlags;   //
+            uint32_t mDevice;                   // current device this output is routed to
+            uint32_t mRefCount[AudioSystem::NUM_STREAM_TYPES]; // number of streams of each type using this output
+        };
+
+        // descriptor for audio inputs. Used to maintain current configuration of each opened audio input
+        // and keep track of the usage of this input.
+        class AudioInputDescriptor
+        {
+        public:
+            AudioInputDescriptor();
+
+            uint32_t mSamplingRate;                     //
+            uint32_t mFormat;                           // input configuration
+            uint32_t mChannels;                         //
+            AudioSystem::audio_in_acoustics mAcoustics; //
+            uint32_t mDevice;                           // current device this input is routed to
+            uint32_t mRefCount;                         // number of AudioRecord clients using this output
+        };
+
+        // stream descriptor used for volume control
+        class StreamDescriptor
+        {
+        public:
+            StreamDescriptor()
+            :   mIndexMin(0), mIndexMax(1), mIndexCur(1), mMuteCount(0), mCanBeMuted(true) {}
+
+            int mIndexMin;      // min volume index
+            int mIndexMax;      // max volume index
+            int mIndexCur;      // current volume index
+            int mMuteCount;     // mute request counter
+            bool mCanBeMuted;   // true is the stream can be muted
+        };
+
+        // return the strategy corresponding to a given stream type
+        static routing_strategy getStrategy(AudioSystem::stream_type stream);
+        // return the output handle of an output routed to the specified device, 0 if no output
+        // is routed to the device
+        float computeVolume(int stream, int index, uint32_t device);
+        // Mute or unmute the stream on the specified output
+        void setStreamMute(int stream, bool on, audio_io_handle_t output);
+        // handle special cases for sonification strategy while in call: mute streams or replace by
+        // a special tone in the device used for communication
+        void handleIncallSonification(int stream, bool starting);
+
+
+#ifdef AUDIO_POLICY_TEST
+        virtual     bool        threadLoop();
+                    void        exit();
+        int testOutputIndex(audio_io_handle_t output);
+#endif //AUDIO_POLICY_TEST
+
+
+        AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
+        audio_io_handle_t mHardwareOutput;              // hardware output handler
+
+        KeyedVector<audio_io_handle_t, AudioOutputDescriptor *> mOutputs;   // list ot output descritors
+        KeyedVector<audio_io_handle_t, AudioInputDescriptor *> mInputs;     // list of input descriptors
+        uint32_t mAvailableOutputDevices;                                   // bit field of all available output devices
+        uint32_t mAvailableInputDevices;                                    // bit field of all available input devices
+        int mPhoneState;                                                    // current phone state
+        uint32_t                 mRingerMode;                               // current ringer mode
+        AudioSystem::forced_config mForceUse[AudioSystem::NUM_FORCE_USE];   // current forced use configuration
+
+        StreamDescriptor mStreams[AudioSystem::NUM_STREAM_TYPES];           // stream descriptors for volume control
+
+#ifdef AUDIO_POLICY_TEST
+        Mutex   mLock;
+        Condition mWaitWorkCV;
+
+        int             mCurOutput;
+        bool            mDirectOutput;
+        audio_io_handle_t mTestOutputs[NUM_TEST_OUTPUTS];
+        int             mTestInput;
+        uint32_t        mTestDevice;
+        uint32_t        mTestSamplingRate;
+        uint32_t        mTestFormat;
+        uint32_t        mTestChannelcount;
+        uint32_t        mTestLatencyMs;
+#endif //AUDIO_POLICY_TEST
+
+};
+
+};
diff --git a/libs/audioflinger/AudioPolicyService.cpp b/libs/audioflinger/AudioPolicyService.cpp
new file mode 100644
index 0000000..7f6c4ed
--- /dev/null
+++ b/libs/audioflinger/AudioPolicyService.cpp
@@ -0,0 +1,650 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#define LOG_TAG "AudioPolicyService"
+//#define LOG_NDEBUG 0
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <cutils/properties.h>
+#include <binder/IPCThreadState.h>
+#include <utils/String16.h>
+#include <utils/threads.h>
+#include "AudioPolicyService.h"
+#include "AudioPolicyManagerGeneric.h"
+#include <cutils/properties.h>
+#include <dlfcn.h>
+
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+namespace android {
+
+static bool checkPermission() {
+#ifndef HAVE_ANDROID_OS
+    return true;
+#endif
+    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+    bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
+    if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
+    return ok;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioPolicyService::AudioPolicyService()
+    : BnAudioPolicyService() , mpPolicyManager(NULL)
+{
+    char value[PROPERTY_VALUE_MAX];
+
+    // start tone playback thread
+    mTonePlaybacThread = new AudioCommandThread();
+    // start audio commands thread
+    mAudioCommandThread = new AudioCommandThread();
+
+#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
+    mpPolicyManager = new AudioPolicyManagerGeneric(this);
+    LOGV("build for GENERIC_AUDIO - using generic audio policy");
+#else
+    // if running in emulation - use the emulator driver
+    if (property_get("ro.kernel.qemu", value, 0)) {
+        LOGV("Running in emulation - using generic audio policy");
+        mpPolicyManager = new AudioPolicyManagerGeneric(this);
+    }
+    else {
+        LOGV("Using hardware specific audio policy");
+        mpPolicyManager = createAudioPolicyManager(this);
+    }
+#endif
+
+    // load properties
+    property_get("ro.camera.sound.forced", value, "0");
+    mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
+}
+
+AudioPolicyService::~AudioPolicyService()
+{
+    mTonePlaybacThread->exit();
+    mTonePlaybacThread.clear();
+    mAudioCommandThread->exit();
+    mAudioCommandThread.clear();
+
+    if (mpPolicyManager) {
+        delete mpPolicyManager;
+    }
+}
+
+
+status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  AudioSystem::device_connection_state state,
+                                                  const char *device_address)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
+        return BAD_VALUE;
+    }
+    if (state != AudioSystem::DEVICE_STATE_AVAILABLE && state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
+        return BAD_VALUE;
+    }
+
+    LOGV("setDeviceConnectionState() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
+}
+
+AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  const char *device_address)
+{
+    if (mpPolicyManager == NULL) {
+        return AudioSystem::DEVICE_STATE_UNAVAILABLE;
+    }
+    if (!checkPermission()) {
+        return AudioSystem::DEVICE_STATE_UNAVAILABLE;
+    }
+    return mpPolicyManager->getDeviceConnectionState(device, device_address);
+}
+
+status_t AudioPolicyService::setPhoneState(int state)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (state < 0 || state >= AudioSystem::NUM_MODES) {
+        return BAD_VALUE;
+    }
+
+    LOGV("setPhoneState() tid %d", gettid());
+
+    // TODO: check if it is more appropriate to do it in platform specific policy manager
+    AudioSystem::setMode(state);
+
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->setPhoneState(state);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+
+    mpPolicyManager->setRingerMode(mode, mask);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
+        return BAD_VALUE;
+    }
+    if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
+        return BAD_VALUE;
+    }
+    LOGV("setForceUse() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->setForceUse(usage, config);
+    return NO_ERROR;
+}
+
+AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
+{
+    if (mpPolicyManager == NULL) {
+        return AudioSystem::FORCE_NONE;
+    }
+    if (!checkPermission()) {
+        return AudioSystem::FORCE_NONE;
+    }
+    if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
+        return AudioSystem::FORCE_NONE;
+    }
+    return mpPolicyManager->getForceUse(usage);
+}
+
+audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::output_flags flags)
+{
+    if (mpPolicyManager == NULL) {
+        return NULL;
+    }
+    LOGV("getOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
+}
+
+status_t AudioPolicyService::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    LOGV("startOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->startOutput(output, stream);
+}
+
+status_t AudioPolicyService::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    LOGV("stopOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->stopOutput(output, stream);
+}
+
+void AudioPolicyService::releaseOutput(audio_io_handle_t output)
+{
+    if (mpPolicyManager == NULL) {
+        return;
+    }
+    LOGV("releaseOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->releaseOutput(output);
+}
+
+audio_io_handle_t AudioPolicyService::getInput(int inputSource,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::audio_in_acoustics acoustics)
+{
+    if (mpPolicyManager == NULL) {
+        return NULL;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
+}
+
+status_t AudioPolicyService::startInput(audio_io_handle_t input)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->startInput(input);
+}
+
+status_t AudioPolicyService::stopInput(audio_io_handle_t input)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->stopInput(input);
+}
+
+void AudioPolicyService::releaseInput(audio_io_handle_t input)
+{
+    if (mpPolicyManager == NULL) {
+        return;
+    }
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->releaseInput(input);
+}
+
+status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
+                                            int indexMin,
+                                            int indexMax)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+        return BAD_VALUE;
+    }
+    mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+        return BAD_VALUE;
+    }
+
+    return mpPolicyManager->setStreamVolumeIndex(stream, index);
+}
+
+status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+        return BAD_VALUE;
+    }
+    return mpPolicyManager->getStreamVolumeIndex(stream, index);
+}
+
+void AudioPolicyService::binderDied(const wp<IBinder>& who) {
+    LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
+}
+
+status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
+{
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        dumpPermissionDenial(fd, args);
+    } else {
+
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::dumpPermissionDenial(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, SIZE, "Permission Denial: "
+            "can't dump AudioPolicyService from pid=%d, uid=%d\n",
+            IPCThreadState::self()->getCallingPid(),
+            IPCThreadState::self()->getCallingUid());
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    return BnAudioPolicyService::onTransact(code, data, reply, flags);
+}
+
+
+// ----------------------------------------------------------------------------
+void AudioPolicyService::instantiate() {
+    defaultServiceManager()->addService(
+            String16("media.audio_policy"), new AudioPolicyService());
+}
+
+
+// ----------------------------------------------------------------------------
+// AudioPolicyClientInterface implementation
+// ----------------------------------------------------------------------------
+
+
+audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t *pLatencyMs,
+                                AudioSystem::output_flags flags)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("openOutput() could not get AudioFlinger");
+        return NULL;
+    }
+
+    return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, pLatencyMs, flags);
+}
+
+audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("openDuplicateOutput() could not get AudioFlinger");
+        return NULL;
+    }
+    return af->openDuplicateOutput(output1, output2);
+}
+
+status_t AudioPolicyService::closeOutput(audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    return af->closeOutput(output);
+}
+
+
+status_t AudioPolicyService::suspendOutput(audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("suspendOutput() could not get AudioFlinger");
+        return PERMISSION_DENIED;
+    }
+
+    return af->suspendOutput(output);
+}
+
+status_t AudioPolicyService::restoreOutput(audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("restoreOutput() could not get AudioFlinger");
+        return PERMISSION_DENIED;
+    }
+
+    return af->restoreOutput(output);
+}
+
+audio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t acoustics)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("openInput() could not get AudioFlinger");
+        return NULL;
+    }
+
+    return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
+}
+
+status_t AudioPolicyService::closeInput(audio_io_handle_t input)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    return af->closeInput(input);
+}
+
+status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output)
+{
+    return mAudioCommandThread->volumeCommand((int)stream, volume, (void *)output);
+}
+
+status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    return af->setStreamOutput(stream, output);
+}
+
+
+void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
+{
+    mAudioCommandThread->parametersCommand((void *)ioHandle, keyValuePairs);
+}
+
+String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
+{
+    String8 result = AudioSystem::getParameters(ioHandle, keys);
+    return result;
+}
+
+status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
+{
+    mTonePlaybacThread->startToneCommand(tone, stream);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::stopTone()
+{
+    mTonePlaybacThread->stopToneCommand();
+    return NO_ERROR;
+}
+
+
+// -----------  AudioPolicyService::AudioCommandThread implementation ----------
+
+AudioPolicyService::AudioCommandThread::AudioCommandThread()
+    :   Thread(false)
+{
+    mpToneGenerator = NULL;
+}
+
+
+AudioPolicyService::AudioCommandThread::~AudioCommandThread()
+{
+    mAudioCommands.clear();
+    if (mpToneGenerator != NULL) delete mpToneGenerator;
+}
+
+void AudioPolicyService::AudioCommandThread::onFirstRef()
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "AudioCommandThread");
+
+    run(buffer, ANDROID_PRIORITY_AUDIO);
+}
+
+bool AudioPolicyService::AudioCommandThread::threadLoop()
+{
+    mLock.lock();
+    while (!exitPending())
+    {
+        while(!mAudioCommands.isEmpty()) {
+            AudioCommand *command = mAudioCommands[0];
+            mAudioCommands.removeAt(0);
+            switch (command->mCommand) {
+            case START_TONE: {
+                mLock.unlock();
+                ToneData *data = (ToneData *)command->mParam;
+                LOGV("AudioCommandThread() processing start tone %d on stream %d",
+                        data->mType, data->mStream);
+                if (mpToneGenerator != NULL)
+                    delete mpToneGenerator;
+                mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
+                mpToneGenerator->startTone(data->mType);
+                delete data;
+                mLock.lock();
+                }break;
+            case STOP_TONE: {
+                mLock.unlock();
+                LOGV("AudioCommandThread() processing stop tone");
+                if (mpToneGenerator != NULL) {
+                    mpToneGenerator->stopTone();
+                    delete mpToneGenerator;
+                    mpToneGenerator = NULL;
+                }
+                mLock.lock();
+                }break;
+            case SET_VOLUME: {
+                VolumeData *data = (VolumeData *)command->mParam;
+                LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %p", data->mStream, data->mVolume, data->mIO);
+                mCommandStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
+                mCommandCond.signal();
+                mWaitWorkCV.wait(mLock);
+                delete data;
+                }break;
+            case SET_PARAMETERS: {
+                 ParametersData *data = (ParametersData *)command->mParam;
+                 LOGV("AudioCommandThread() processing set parameters string %s, io %p", data->mKeyValuePairs.string(), data->mIO);
+                 mCommandStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
+                 mCommandCond.signal();
+                 mWaitWorkCV.wait(mLock);
+                 delete data;
+                 }break;
+            default:
+                LOGW("AudioCommandThread() unknown command %d", command->mCommand);
+            }
+            delete command;
+        }
+        LOGV("AudioCommandThread() going to sleep");
+        mWaitWorkCV.wait(mLock);
+        LOGV("AudioCommandThread() waking up");
+    }
+    mLock.unlock();
+    return false;
+}
+
+void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
+{
+    Mutex::Autolock _l(mLock);
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = START_TONE;
+    ToneData *data = new ToneData();
+    data->mType = type;
+    data->mStream = stream;
+    command->mParam = (void *)data;
+    mAudioCommands.add(command);
+    LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
+    mWaitWorkCV.signal();
+}
+
+void AudioPolicyService::AudioCommandThread::stopToneCommand()
+{
+    Mutex::Autolock _l(mLock);
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = STOP_TONE;
+    command->mParam = NULL;
+    mAudioCommands.add(command);
+    LOGV("AudioCommandThread() adding tone stop");
+    mWaitWorkCV.signal();
+}
+
+status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, void *output)
+{
+    Mutex::Autolock _l(mLock);
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_VOLUME;
+    VolumeData *data = new VolumeData();
+    data->mStream = stream;
+    data->mVolume = volume;
+    data->mIO = output;
+    command->mParam = data;
+    mAudioCommands.add(command);
+    LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %p", stream, volume, output);
+    mWaitWorkCV.signal();
+    mCommandCond.wait(mLock);
+    status_t status =  mCommandStatus;
+    mWaitWorkCV.signal();
+    return status;
+}
+
+status_t AudioPolicyService::AudioCommandThread::parametersCommand(void *ioHandle, const String8& keyValuePairs)
+{
+    Mutex::Autolock _l(mLock);
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_PARAMETERS;
+    ParametersData *data = new ParametersData();
+    data->mIO = ioHandle;
+    data->mKeyValuePairs = keyValuePairs;
+    command->mParam = data;
+    mAudioCommands.add(command);
+    LOGV("AudioCommandThread() adding set parameter string %s, io %p", keyValuePairs.string(), ioHandle);
+    mWaitWorkCV.signal();
+    mCommandCond.wait(mLock);
+    status_t status =  mCommandStatus;
+    mWaitWorkCV.signal();
+    return status;
+}
+
+void AudioPolicyService::AudioCommandThread::exit()
+{
+    LOGV("AudioCommandThread::exit");
+    {
+        AutoMutex _l(mLock);
+        requestExit();
+        mWaitWorkCV.signal();
+    }
+    requestExitAndWait();
+}
+
+}; // namespace android
diff --git a/libs/audioflinger/AudioPolicyService.h b/libs/audioflinger/AudioPolicyService.h
new file mode 100644
index 0000000..1c46975
--- /dev/null
+++ b/libs/audioflinger/AudioPolicyService.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef ANDROID_AUDIOPOLICYSERVICE_H
+#define ANDROID_AUDIOPOLICYSERVICE_H
+
+#include <media/IAudioPolicyService.h>
+#include <hardware_legacy/AudioPolicyInterface.h>
+#include <media/ToneGenerator.h>
+
+namespace android {
+
+class String8;
+
+// ----------------------------------------------------------------------------
+
+class AudioPolicyService: public BnAudioPolicyService, public AudioPolicyClientInterface, public IBinder::DeathRecipient
+{
+
+public:
+    static  void        instantiate();
+
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+
+    //
+    // BnAudioPolicyService (see AudioPolicyInterface for method descriptions)
+    //
+
+    virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
+                                              AudioSystem::device_connection_state state,
+                                              const char *device_address);
+    virtual AudioSystem::device_connection_state getDeviceConnectionState(AudioSystem::audio_devices device,
+                                                                          const char *device_address);
+    virtual status_t setPhoneState(int state);
+    virtual status_t setRingerMode(uint32_t mode, uint32_t mask);
+    virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config);
+    virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage);
+    virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream,
+                                        uint32_t samplingRate = 0,
+                                        uint32_t format = AudioSystem::FORMAT_DEFAULT,
+                                        uint32_t channels = 0,
+                                        AudioSystem::output_flags flags = AudioSystem::OUTPUT_FLAG_INDIRECT);
+    virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+    virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+    virtual void releaseOutput(audio_io_handle_t output);
+    virtual audio_io_handle_t getInput(int inputSource,
+                                    uint32_t samplingRate = 0,
+                                    uint32_t format = AudioSystem::FORMAT_DEFAULT,
+                                    uint32_t channels = 0,
+                                    AudioSystem::audio_in_acoustics acoustics = (AudioSystem::audio_in_acoustics)0);
+    virtual status_t startInput(audio_io_handle_t input);
+    virtual status_t stopInput(audio_io_handle_t input);
+    virtual void releaseInput(audio_io_handle_t input);
+    virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+                                      int indexMin,
+                                      int indexMax);
+    virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index);
+    virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
+
+    virtual     status_t    onTransact(
+                                uint32_t code,
+                                const Parcel& data,
+                                Parcel* reply,
+                                uint32_t flags);
+
+    // IBinder::DeathRecipient
+    virtual     void        binderDied(const wp<IBinder>& who);
+
+    //
+    // AudioPolicyClientInterface
+    //
+    virtual audio_io_handle_t openOutput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t *pLatencyMs,
+                                    AudioSystem::output_flags flags);
+    virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2);
+    virtual status_t closeOutput(audio_io_handle_t output);
+    virtual status_t suspendOutput(audio_io_handle_t output);
+    virtual status_t restoreOutput(audio_io_handle_t output);
+    virtual audio_io_handle_t openInput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t acoustics);
+    virtual status_t closeInput(audio_io_handle_t input);
+    virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output);
+    virtual status_t setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output);
+    virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
+    virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
+    virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream);
+    virtual status_t stopTone();
+
+private:
+                        AudioPolicyService();
+    virtual             ~AudioPolicyService();
+
+    // Thread used for tone playback and to send audio config commands to audio flinger
+    // For tone playback, using a separate thread is necessary to avoid deadlock with mLock because startTone()
+    // and stopTone() are normally called with mLock locked and requesting a tone start or stop will cause
+    // calls to AudioPolicyService and an attempt to lock mLock.
+    // For audio config commands, it is necessary because audio flinger requires that the calling process (user)
+    // has permission to modify audio settings.
+    class AudioCommandThread : public Thread {
+    public:
+
+        // commands for tone AudioCommand
+        enum {
+            START_TONE,
+            STOP_TONE,
+            SET_VOLUME,
+            SET_PARAMETERS
+        };
+
+        AudioCommandThread ();
+        virtual             ~AudioCommandThread();
+
+        // Thread virtuals
+        virtual     void        onFirstRef();
+        virtual     bool        threadLoop();
+
+                    void        exit();
+                    void        startToneCommand(int type = 0, int stream = 0);
+                    void        stopToneCommand();
+                    status_t    volumeCommand(int stream, float volume, void *output);
+                    status_t    parametersCommand(void *ioHandle, const String8& keyValuePairs);
+
+    private:
+        // descriptor for requested tone playback event
+        class AudioCommand {
+        public:
+            int mCommand;   // START_TONE, STOP_TONE ...
+            void *mParam;
+        };
+
+        class ToneData {
+        public:
+            int mType;      // tone type (START_TONE only)
+            int mStream;    // stream type (START_TONE only)
+        };
+
+        class VolumeData {
+        public:
+            int mStream;
+            float mVolume;
+            void *mIO;
+        };
+        class ParametersData {
+        public:
+            void *mIO;
+            String8 mKeyValuePairs;
+        };
+
+
+        Mutex   mLock;
+        Condition mWaitWorkCV;
+        Vector<AudioCommand *> mAudioCommands;    // list of pending tone events
+        Condition              mCommandCond;
+        status_t               mCommandStatus;
+        ToneGenerator *mpToneGenerator;     // the tone generator
+    };
+
+    // Internal dump utilities.
+    status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
+
+
+    Mutex   mLock;      // prevents concurrent access to AudioPolicy manager functions changing device
+                        // connection stated our routing
+    AudioPolicyInterface* mpPolicyManager;          // the platform specific policy manager
+    sp <AudioCommandThread> mAudioCommandThread;    // audio commands thread
+    sp <AudioCommandThread> mTonePlaybacThread;     // tone playback thread
+};
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOPOLICYSERVICE_H
+
+
+
+
+
+
+
+
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 0091e32..6b11a25 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -1,4 +1,3 @@
-# Only build if BUILD_RENDERSCRIPT is defined to true in the environment.
 ifeq ($(BUILD_RENDERSCRIPT),true)
 
 LOCAL_PATH:=$(call my-dir)
@@ -106,16 +105,13 @@
 LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL libGLESv1_CM libui libacc
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libRS
-LOCAL_PRELINK_MODULE := false
-
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_SHARED_LIBRARY)
 
 # Include the subdirectories ====================
 include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk,\
-            jni \
             java \
     	))
 
-endif # BUILD_RENDERSCRIPT
+endif
\ No newline at end of file
diff --git a/libs/rs/java/Film/Android.mk b/libs/rs/java/Film/Android.mk
index 2e9c243..b7f98fc 100644
--- a/libs/rs/java/Film/Android.mk
+++ b/libs/rs/java/Film/Android.mk
@@ -18,7 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
 
 LOCAL_PACKAGE_NAME := Film
 
diff --git a/libs/rs/java/Fountain/Android.mk b/libs/rs/java/Fountain/Android.mk
index af3d5fc..b6a9f10 100644
--- a/libs/rs/java/Fountain/Android.mk
+++ b/libs/rs/java/Fountain/Android.mk
@@ -18,7 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
 
 LOCAL_PACKAGE_NAME := Fountain
 
diff --git a/libs/rs/java/RenderScript/Android.mk b/libs/rs/java/RenderScript/Android.mk
deleted file mode 100644
index 616fbd2..0000000
--- a/libs/rs/java/RenderScript/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2008 Esmertec AG.
-# Copyright (C) 2008 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)
-
-# the library
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-            $(call all-subdir-java-files) 
-
-LOCAL_MODULE:= android.renderscript
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/libs/rs/java/Rollo/Android.mk b/libs/rs/java/Rollo/Android.mk
index 1c6dfdf..5a4957c 100644
--- a/libs/rs/java/Rollo/Android.mk
+++ b/libs/rs/java/Rollo/Android.mk
@@ -18,7 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
 
 LOCAL_PACKAGE_NAME := Rollo
 
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 2d949a0..90e7f50 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -575,6 +575,7 @@
     mFormat = overlay->format; 
     mWidthStride = overlay->w_stride;
     mHeightStride = overlay->h_stride;
+    mInitialized = false;
 
     mOverlayHandle = overlay->getHandleRef(overlay);
     
@@ -614,8 +615,9 @@
     // this code-path must be as tight as possible, it's called each time
     // the screen is composited.
     if (UNLIKELY(mOverlay != 0)) {
-        if (mVisibilityChanged) {
+        if (mVisibilityChanged || !mInitialized) {
             mVisibilityChanged = false;
+            mInitialized = true;
             const Rect& bounds = mLayer.getTransformedBounds();
             int x = bounds.left;
             int y = bounds.top;
@@ -627,7 +629,7 @@
             if (mOverlay) {
                 overlay_control_device_t* overlay_dev = mOverlayDevice;
                 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
-                overlay_dev->setParameter(overlay_dev, mOverlay, 
+                overlay_dev->setParameter(overlay_dev, mOverlay,
                         OVERLAY_TRANSFORM, mLayer.getOrientation());
                 overlay_dev->commit(overlay_dev, mOverlay);
             }
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 746790b..8057219 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -175,6 +175,7 @@
         int32_t mWidthStride;
         int32_t mHeightStride;
         mutable Mutex mLock;
+        bool mInitialized;
     };
 
 
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 0732b61..500f6a4 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -37,15 +37,58 @@
     public static final int ENCODING_PCM_8BIT = 3;  // accessed by native code
 
     /** Invalid audio channel configuration */
-    public static final int CHANNEL_CONFIGURATION_INVALID   = 0;
+    /** @deprecated use CHANNEL_INVALID instead  */
+    @Deprecated    public static final int CHANNEL_CONFIGURATION_INVALID   = 0;
     /** Default audio channel configuration */
-    public static final int CHANNEL_CONFIGURATION_DEFAULT   = 1;
+    /** @deprecated use CHANNEL_OUT_DEFAULT or CHANNEL_IN_DEFAULT instead  */
+    @Deprecated    public static final int CHANNEL_CONFIGURATION_DEFAULT   = 1;
     /** Mono audio configuration */
-    public static final int CHANNEL_CONFIGURATION_MONO      = 2;
+    /** @deprecated use CHANNEL_OUT_MONO or CHANNEL_IN_MONO instead  */
+    @Deprecated    public static final int CHANNEL_CONFIGURATION_MONO      = 2;
     /** Stereo (2 channel) audio configuration */
-    public static final int CHANNEL_CONFIGURATION_STEREO    = 3;
+    /** @deprecated use CHANNEL_OUT_STEREO or CHANNEL_IN_STEREO instead  */
+    @Deprecated    public static final int CHANNEL_CONFIGURATION_STEREO    = 3;
+
+    /** Invalid audio channel mask */
+    public static final int CHANNEL_INVALID   = -1;
+    /** Default audio channel mask */
+    // Channel mask definitions must be kept in sync with native values in include/media/AudioSystem.h
+    public static final int CHANNEL_OUT_DEFAULT = 0;
+    public static final int CHANNEL_OUT_FRONT_LEFT = 0x1;
+    public static final int CHANNEL_OUT_FRONT_RIGHT = 0x2;
+    public static final int CHANNEL_OUT_FRONT_CENTER = 0x4;
+    public static final int CHANNEL_OUT_LOW_FREQUENCY = 0x8;
+    public static final int CHANNEL_OUT_BACK_LEFT = 0x10;
+    public static final int CHANNEL_OUT_BACK_RIGHT = 0x20;
+    public static final int CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40;
+    public static final int CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80;
+    public static final int CHANNEL_OUT_BACK_CENTER = 0x100;
+    public static final int CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT;
+    public static final int CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT);
+    public static final int CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+            CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT);
+    public static final int CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+            CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER);
+    public static final int CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+            CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT);
+    public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+            CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
+            CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER);
+
+    public static final int CHANNEL_IN_DEFAULT = 0;
+    public static final int CHANNEL_IN_LEFT = 0x10000;
+    public static final int CHANNEL_IN_RIGHT = 0x20000;
+    public static final int CHANNEL_IN_FRONT = 0x40000;
+    public static final int CHANNEL_IN_BACK = 0x80000;
+    public static final int CHANNEL_IN_LEFT_PROCESSED = 0x100000;
+    public static final int CHANNEL_IN_RIGHT_PROCESSED = 0x200000;
+    public static final int CHANNEL_IN_FRONT_PROCESSED = 0x400000;
+    public static final int CHANNEL_IN_BACK_PROCESSED = 0x800000;
+    public static final int CHANNEL_IN_PRESSURE = 0x1000000;
+    public static final int CHANNEL_IN_X_AXIS = 0x2000000;
+    public static final int CHANNEL_IN_Y_AXIS = 0x4000000;
+    public static final int CHANNEL_IN_Z_AXIS = 0x8000000;
+    public static final int CHANNEL_IN_MONO = CHANNEL_IN_FRONT;
+    public static final int CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT);
 
 }
-
-
-
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a65a417..040d4bc 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -140,11 +140,17 @@
     public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;
     /** @hide The audio stream for phone calls when connected to bluetooth */
     public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;
+    /** @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */
+    public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED;
+    /** The audio stream for DTMF Tones */
+    public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF;
+    /** @hide The audio stream for text to speech (TTS) */
+    public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
     /** Number of audio streams */
     /**
      * @deprecated Use AudioSystem.getNumStreamTypes() instead
      */
-    public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS;
+    @Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS;
 
 
     /** @hide Maximum volume index values for audio streams */
@@ -156,6 +162,9 @@
         8,  // STREAM_ALARM
         8,  // STREAM_NOTIFICATION
         16, // STREAM_BLUETOOTH_SCO
+        8,  // STREAM_SYSTEM_ENFORCED
+        16, // STREAM_DTMF
+        16  // STREAM_TTS
     };
 
     /**  @hide Default volume index values for audio streams */
@@ -166,7 +175,10 @@
         11, // STREAM_MUSIC
         6,  // STREAM_ALARM
         5,  // STREAM_NOTIFICATION
-        7   // STREAM_BLUETOOTH_SCO
+        7,  // STREAM_BLUETOOTH_SCO
+        5,  // STREAM_SYSTEM_ENFORCED
+        11, // STREAM_DTMF
+        11  // STREAM_TTS
     };
 
     /**
@@ -637,9 +649,11 @@
      *           <var>false</var> to turn it off
      */
     public void setSpeakerphoneOn(boolean on){
-        // Temporary fix for issue #1713090 until audio routing is refactored in eclair release.
-        // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager
-        setRoutingP(MODE_INVALID, on ? ROUTE_SPEAKER: 0, ROUTE_SPEAKER);
+        if (on) {
+            AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_SPEAKER);
+        } else {
+            AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE);
+        }
     }
 
     /**
@@ -648,41 +662,47 @@
      * @return true if speakerphone is on, false if it's off
      */
     public boolean isSpeakerphoneOn() {
-        return (getRoutingP(MODE_IN_CALL) & ROUTE_SPEAKER) == 0 ? false : true;
+        if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) == AudioSystem.FORCE_SPEAKER) {
+            return true;
+        } else {
+            return false;
+        }
      }
 
     /**
-     * Sets audio routing to the Bluetooth headset on or off.
+     * Request use of Bluetooth SCO headset for communications.
      *
-     * @param on set <var>true</var> to route SCO (voice) audio to/from Bluetooth
-     *           headset; <var>false</var> to route audio to/from phone earpiece
+     * @param on set <var>true</var> to use bluetooth SCO for communications;
+     *               <var>false</var> to not use bluetooth SCO for communications
      */
     public void setBluetoothScoOn(boolean on){
-        // Temporary fix for issue #1713090 until audio routing is refactored in eclair release.
-        // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager
-        setRoutingP(MODE_INVALID, on ? ROUTE_BLUETOOTH_SCO: 0, ROUTE_BLUETOOTH_SCO);
+        if (on) {
+            AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO);
+        } else {
+            AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE);
+        }
     }
 
     /**
-     * Checks whether audio routing to the Bluetooth headset is on or off.
+     * Checks whether communications use Bluetooth SCO.
      *
-     * @return true if SCO audio is being routed to/from Bluetooth headset;
+     * @return true if SCO is used for communications;
      *         false if otherwise
      */
     public boolean isBluetoothScoOn() {
-        return (getRoutingP(MODE_IN_CALL) & ROUTE_BLUETOOTH_SCO) == 0 ? false : true;
+        if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) == AudioSystem.FORCE_BT_SCO) {
+            return true;
+        } else {
+            return false;
+        }
     }
 
     /**
-     * Sets A2DP audio routing to the Bluetooth headset on or off.
-     *
      * @param on set <var>true</var> to route A2DP audio to/from Bluetooth
      *           headset; <var>false</var> disable A2DP audio
+     * @deprecated Do not use.
      */
-    public void setBluetoothA2dpOn(boolean on){
-        // Temporary fix for issue #1713090 until audio routing is refactored in eclair release.
-        // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager
-        setRoutingP(MODE_INVALID, on ? ROUTE_BLUETOOTH_A2DP: 0, ROUTE_BLUETOOTH_A2DP);
+    @Deprecated public void setBluetoothA2dpOn(boolean on){
     }
 
     /**
@@ -692,7 +712,12 @@
      *         false if otherwise
      */
     public boolean isBluetoothA2dpOn() {
-        return (getRoutingP(MODE_NORMAL) & ROUTE_BLUETOOTH_A2DP) == 0 ? false : true;
+        if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,"") 
+            == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
+            return false;
+        } else {
+            return true;
+        }
     }
 
     /**
@@ -700,12 +725,9 @@
      *
      * @param on set <var>true</var> to route audio to/from wired
      *           headset; <var>false</var> disable wired headset audio
-     * @hide
+     * @deprecated Do not use.
      */
-    public void setWiredHeadsetOn(boolean on){
-        // Temporary fix for issue #1713090 until audio routing is refactored in eclair release.
-        // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager
-        setRoutingP(MODE_INVALID, on ? ROUTE_HEADSET: 0, ROUTE_HEADSET);
+    @Deprecated public void setWiredHeadsetOn(boolean on){
     }
 
     /**
@@ -713,10 +735,14 @@
      *
      * @return true if audio is being routed to/from wired headset;
      *         false if otherwise
-     * @hide
      */
     public boolean isWiredHeadsetOn() {
-        return (getRoutingP(MODE_NORMAL) & ROUTE_HEADSET) == 0 ? false : true;
+        if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,"") 
+                == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
+            return false;
+        } else {
+            return true;
+        }
     }
 
     /**
@@ -726,12 +752,7 @@
      *           <var>false</var> to turn mute off
      */
     public void setMicrophoneMute(boolean on){
-        IAudioService service = getService();
-        try {
-            service.setMicrophoneMute(on);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setMicrophoneMute", e);
-        }
+        AudioSystem.muteMicrophone(on);
     }
 
     /**
@@ -740,13 +761,7 @@
      * @return true if microphone is muted, false if it's not
      */
     public boolean isMicrophoneMute() {
-        IAudioService service = getService();
-        try {
-            return service.isMicrophoneMute();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in isMicrophoneMute", e);
-            return false;
-        }
+        return AudioSystem.isMicrophoneMuted();
     }
 
     /**
@@ -809,32 +824,39 @@
     /* Routing bits for setRouting/getRouting API */
     /**
      * Routing audio output to earpiece
+     * @deprecated
      */
-    public static final int ROUTE_EARPIECE          = AudioSystem.ROUTE_EARPIECE;
+    @Deprecated public static final int ROUTE_EARPIECE          = AudioSystem.ROUTE_EARPIECE;
     /**
      * Routing audio output to spaker
+     * @deprecated
      */
-    public static final int ROUTE_SPEAKER           = AudioSystem.ROUTE_SPEAKER;
+    @Deprecated public static final int ROUTE_SPEAKER           = AudioSystem.ROUTE_SPEAKER;
     /**
      * @deprecated use {@link #ROUTE_BLUETOOTH_SCO}
+     * @deprecated
      */
     @Deprecated public static final int ROUTE_BLUETOOTH = AudioSystem.ROUTE_BLUETOOTH_SCO;
     /**
      * Routing audio output to bluetooth SCO
+     * @deprecated
      */
-    public static final int ROUTE_BLUETOOTH_SCO     = AudioSystem.ROUTE_BLUETOOTH_SCO;
+    @Deprecated public static final int ROUTE_BLUETOOTH_SCO     = AudioSystem.ROUTE_BLUETOOTH_SCO;
     /**
      * Routing audio output to headset
+     * @deprecated
      */
-    public static final int ROUTE_HEADSET           = AudioSystem.ROUTE_HEADSET;
+    @Deprecated public static final int ROUTE_HEADSET           = AudioSystem.ROUTE_HEADSET;
     /**
      * Routing audio output to bluetooth A2DP
+     * @deprecated
      */
-    public static final int ROUTE_BLUETOOTH_A2DP    = AudioSystem.ROUTE_BLUETOOTH_A2DP;
+    @Deprecated public static final int ROUTE_BLUETOOTH_A2DP    = AudioSystem.ROUTE_BLUETOOTH_A2DP;
     /**
      * Used for mask parameter of {@link #setRouting(int,int,int)}.
+     * @deprecated
      */
-    public static final int ROUTE_ALL               = AudioSystem.ROUTE_ALL;
+    @Deprecated public static final int ROUTE_ALL               = AudioSystem.ROUTE_ALL;
 
     /**
      * Sets the audio routing for a specified mode
@@ -846,16 +868,10 @@
      * ROUTE_xxx types. Unset bits indicate the route should be left unchanged
      *
      * @deprecated   Do not set audio routing directly, use setSpeakerphoneOn(),
-     * setBluetoothScoOn(), setBluetoothA2dpOn() and setWiredHeadsetOn() methods instead.
+     * setBluetoothScoOn() methods instead.
      */
-
+    @Deprecated
     public void setRouting(int mode, int routes, int mask) {
-        IAudioService service = getService();
-        try {
-            service.setRouting(mode, routes, mask);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setRouting", e);
-        }
     }
 
     /**
@@ -869,13 +885,7 @@
      */
     @Deprecated
     public int getRouting(int mode) {
-        IAudioService service = getService();
-        try {
-            return service.getRouting(mode);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in getRouting", e);
-            return -1;
-        }
+        return -1;
     }
 
     /**
@@ -884,13 +894,7 @@
      * @return true if any music tracks are active.
      */
     public boolean isMusicActive() {
-        IAudioService service = getService();
-        try {
-            return service.isMusicActive();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in isMusicActive", e);
-            return false;
-        }
+        return AudioSystem.isMusicActive();
     }
 
     /*
@@ -906,14 +910,32 @@
      */
     /**
      * @hide
+     * @deprecated Use {@link #setPrameters(String)} instead
      */
-    public void setParameter(String key, String value) {
-        IAudioService service = getService();
-        try {
-            service.setParameter(key, value);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setParameter", e);
-        }
+    @Deprecated public void setParameter(String key, String value) {
+        setParameters(key+"="+value);
+    }
+
+    /**
+     * Sets a variable number of parameter values to audio hardware.
+     *
+     * @param keyValuePairs list of parameters key value pairs in the form:
+     *    key1=value1;key2=value2;...
+     *
+     */
+    public void setParameters(String keyValuePairs) {
+        AudioSystem.setParameters(keyValuePairs);
+    }
+
+    /**
+     * Sets a varaible number of parameter values to audio hardware.
+     *
+     * @param keys list of parameters
+     * @return list of parameters key value pairs in the form:
+     *    key1=value1;key2=value2;...
+     */
+    public String getParameters(String keys) {
+        return AudioSystem.getParameters(keys);
     }
 
     /* Sound effect identifiers */
@@ -1082,31 +1104,4 @@
       * {@hide}
       */
      private IBinder mICallBack = new Binder();
-
-     /**
-      * {@hide}
-      */
-     private void setRoutingP(int mode, int routes, int mask) {
-         IAudioService service = getService();
-         try {
-             service.setRouting(mode, routes, mask);
-         } catch (RemoteException e) {
-             Log.e(TAG, "Dead object in setRouting", e);
-         }
-     }
-
-
-     /**
-      * {@hide}
-      */
-     private int getRoutingP(int mode) {
-         IAudioService service = getService();
-         try {
-             return service.getRouting(mode);
-         } catch (RemoteException e) {
-             Log.e(TAG, "Dead object in getRouting", e);
-             return -1;
-         }
-     }
-
 }
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 4d1535f9..d96331f 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -86,7 +86,7 @@
     public static final int ERROR_INVALID_OPERATION = -3;
     
     private static final int AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT      = -16;
-    private static final int AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT = -17;
+    private static final int AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK  = -17;
     private static final int AUDIORECORD_ERROR_SETUP_INVALIDFORMAT       = -18;
     private static final int AUDIORECORD_ERROR_SETUP_INVALIDSOURCE       = -19;
     private static final int AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED    = -20;
@@ -135,7 +135,7 @@
     /**
      * The current audio channel configuration
      */
-    private int mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+    private int mChannelConfiguration = AudioFormat.CHANNEL_IN_MONO;
     /**
      * The encoding of the audio samples.
      * @see AudioFormat#ENCODING_PCM_8BIT
@@ -193,8 +193,8 @@
      * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but
      *   not limited to) 44100, 22050 and 11025.
      * @param channelConfig describes the configuration of the audio channels. 
-     *   See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and
-     *   {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
+     *   See {@link AudioFormat#CHANNEL_IN_MONO} and
+     *   {@link AudioFormat#CHANNEL_IN_STEREO}
      * @param audioFormat the format in which the audio data is represented. 
      *   See {@link AudioFormat#ENCODING_PCM_16BIT} and 
      *   {@link AudioFormat#ENCODING_PCM_8BIT}
@@ -265,18 +265,18 @@
         //--------------
         // channel config
         switch (channelConfig) {
-        case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT:
-        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
+        case AudioFormat.CHANNEL_IN_DEFAULT:
+        case AudioFormat.CHANNEL_IN_MONO:
             mChannelCount = 1;
-            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+            mChannelConfiguration = AudioFormat.CHANNEL_IN_MONO;
             break;
-        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
+        case AudioFormat.CHANNEL_IN_STEREO:
             mChannelCount = 2;
-            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+            mChannelConfiguration = AudioFormat.CHANNEL_IN_STEREO;
             break;
         default:
             mChannelCount = 0;
-        mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_INVALID;
+        mChannelConfiguration = AudioFormat.CHANNEL_INVALID;
         throw (new IllegalArgumentException("Unsupported channel configuration."));
         }
 
@@ -368,8 +368,8 @@
 
     /**
      * Returns the configured channel configuration. 
-     * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO}
-     * and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}.
+     * See {@link AudioFormat#CHANNEL_IN_MONO}
+     * and {@link AudioFormat#CHANNEL_IN_STEREO}.
      */
     public int getChannelConfiguration() {
         return mChannelConfiguration;
@@ -425,8 +425,8 @@
      * will be polled for new data.
      * @param sampleRateInHz the sample rate expressed in Hertz.
      * @param channelConfig describes the configuration of the audio channels. 
-     *   See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and
-     *   {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
+     *   See {@link AudioFormat#CHANNEL_IN_MONO} and
+     *   {@link AudioFormat#CHANNEL_IN_STEREO}
      * @param audioFormat the format in which the audio data is represented. 
      *   See {@link AudioFormat#ENCODING_PCM_16BIT}.
      * @return {@link #ERROR_BAD_VALUE} if the recording parameters are not supported by the 
@@ -438,14 +438,14 @@
     static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
         int channelCount = 0;
         switch(channelConfig) {
-        case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT:
-        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
+        case AudioFormat.CHANNEL_IN_DEFAULT:
+        case AudioFormat.CHANNEL_IN_MONO:
             channelCount = 1;
             break;
-        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
+        case AudioFormat.CHANNEL_IN_STEREO:
             channelCount = 2;
             break;
-        case AudioFormat.CHANNEL_CONFIGURATION_INVALID:
+        case AudioFormat.CHANNEL_INVALID:
         default:
             loge("getMinBufferSize(): Invalid channel configuration.");
             return AudioRecord.ERROR_BAD_VALUE;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 58c04f3..30640c3 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -20,6 +20,12 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
+import android.bluetooth.BluetoothIntent;
+import android.content.BroadcastReceiver;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothA2dp;
+
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.media.MediaPlayer.OnCompletionListener;
@@ -94,16 +100,10 @@
     /** @see VolumeStreamState */
     private VolumeStreamState[] mStreamStates;
     private SettingsObserver mSettingsObserver;
-    
-    private boolean mMicMute;
+
     private int mMode;
-    private int[] mRoutes = new int[AudioSystem.NUM_MODES];
     private Object mSettingsLock = new Object();
     private boolean mMediaServerOk;
-    private boolean mSpeakerIsOn;
-    private boolean mBluetoothScoIsConnected;
-    private boolean mHeadsetIsConnected;
-    private boolean mBluetoothA2dpIsConnected;
 
     private SoundPool mSoundPool;
     private Object mSoundEffectsLock = new Object();
@@ -135,6 +135,23 @@
         {4, -1}   // FX_FOCUS_RETURN
     };
 
+    /* STREAM_VOLUME_ALIAS[] indicates for each stream if it uses the volume settings
+     * of another stream: This avoids multiplying the volume settings for hidden
+     * stream types that follow other stream behavior for volume settings
+     * NOTE: do not create loops in aliases! */
+    private int[] STREAM_VOLUME_ALIAS = new int[] {
+        AudioSystem.STREAM_VOICE_CALL,  // STREAM_VOICE_CALL
+        AudioSystem.STREAM_SYSTEM,  // STREAM_SYSTEM
+        AudioSystem.STREAM_RING,  // STREAM_RING
+        AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
+        AudioSystem.STREAM_ALARM,  // STREAM_ALARM
+        AudioSystem.STREAM_NOTIFICATION,  // STREAM_NOTIFICATION
+        AudioSystem.STREAM_VOICE_CALL, // STREAM_BLUETOOTH_SCO
+        AudioSystem.STREAM_SYSTEM,  // STREAM_SYSTEM_ENFORCED
+        AudioSystem.STREAM_VOICE_CALL, // STREAM_DTMF
+        AudioSystem.STREAM_MUSIC  // STREAM_TTS
+    };
+
     private AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
         public void onError(int error) {
             switch (error) {
@@ -178,6 +195,21 @@
      */
     private int mVibrateSetting;
 
+    /** @see System#NOTIFICATIONS_USE_RING_VOLUME */
+    private int mNotificationsUseRingVolume;
+
+    // Broadcast receiver for device connections intent broadcasts
+    private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
+
+    //TODO: use common definitions with HeadsetObserver
+    private static final int BIT_HEADSET = (1 << 0);
+    private static final int BIT_HEADSET_NO_MIC = (1 << 1);
+    private static final int BIT_TTY = (1 << 2);
+    private static final int BIT_FM_HEADSET = (1 << 3);
+    private static final int BIT_FM_SPEAKER = (1 << 4);
+
+    private int mHeadsetState;
+
     ///////////////////////////////////////////////////////////////////////////
     // Construction
     ///////////////////////////////////////////////////////////////////////////
@@ -188,18 +220,20 @@
         mContentResolver = context.getContentResolver();
         mVolumePanel = new VolumePanel(context, this);
         mSettingsObserver = new SettingsObserver();
-        
+
         createAudioSystemThread();
-        createStreamStates();
         readPersistedSettings();
-        readAudioSettings();
+        createStreamStates();
         mMediaServerOk = true;
         AudioSystem.setErrorCallback(mAudioSystemCallback);
         loadSoundEffects();
-        mSpeakerIsOn = false;
-        mBluetoothScoIsConnected = false;
-        mHeadsetIsConnected = false;
-        mBluetoothA2dpIsConnected = false;
+
+        // Register for device connection intent broadcasts.
+        IntentFilter intentFilter =
+                new IntentFilter(Intent.ACTION_HEADSET_PLUG);
+        intentFilter.addAction(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
+        intentFilter.addAction(BluetoothIntent.HEADSET_AUDIO_STATE_CHANGED_ACTION);
+        context.registerReceiver(mReceiver, intentFilter);
     }
 
     private void createAudioSystemThread() {
@@ -223,65 +257,25 @@
     }
 
     private void createStreamStates() {
-        final int[] volumeLevelsPhone =
-            createVolumeLevels(0, AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_VOICE_CALL]);
-        final int[] volumeLevelsCoarse =
-            createVolumeLevels(0, AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_SYSTEM]);
-        final int[] volumeLevelsFine =
-            createVolumeLevels(0, AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_MUSIC]);
-        final int[] volumeLevelsBtPhone =
-            createVolumeLevels(0,
-                    AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]);
-
         int numStreamTypes = AudioSystem.getNumStreamTypes();
         VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
 
         for (int i = 0; i < numStreamTypes; i++) {
-            final int[] levels;
+            streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[STREAM_VOLUME_ALIAS[i]], i);
+        }
 
-            switch (i) {
-
-                case AudioSystem.STREAM_MUSIC:
-                    levels = volumeLevelsFine;
-                    break;
-
-                case AudioSystem.STREAM_VOICE_CALL:
-                    levels = volumeLevelsPhone;
-                    break;
-
-                case AudioSystem.STREAM_BLUETOOTH_SCO:
-                    levels = volumeLevelsBtPhone;
-                    break;
-
-                default:
-                    levels = volumeLevelsCoarse;
-                    break;
-            }
-
-            if (i == AudioSystem.STREAM_BLUETOOTH_SCO) {
-                streams[i] = new VolumeStreamState(AudioManager.DEFAULT_STREAM_VOLUME[i], i,levels);
-            } else {
-                streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[i], i, levels);
+        // Correct stream index values for streams with aliases
+        for (int i = 0; i < numStreamTypes; i++) {
+            if (STREAM_VOLUME_ALIAS[i] != i) {
+                int index = rescaleIndex(streams[i].mIndex, STREAM_VOLUME_ALIAS[i], i);
+                streams[i].mIndex = streams[i].getValidIndex(index);
+                setStreamVolumeIndex(i, index);
+                index = rescaleIndex(streams[i].mLastAudibleIndex, STREAM_VOLUME_ALIAS[i], i);
+                streams[i].mLastAudibleIndex = streams[i].getValidIndex(index);
             }
         }
     }
 
-    private static int[] createVolumeLevels(int offset, int numlevels) {
-        double curve = 1.0f; // 1.4f
-        int [] volumes = new int[numlevels + offset];
-        for (int i = 0; i < offset; i++) {
-            volumes[i] = 0;
-        }
-
-        double val = 0;
-        double max = Math.pow(numlevels - 1, curve);
-        for (int i = 0; i < numlevels; i++) {
-            val = Math.pow(i, curve) / max;
-            volumes[offset + i] = (int) (val * 100.0f);
-        }
-        return volumes;
-    }
-
     private void readPersistedSettings() {
         final ContentResolver cr = mContentResolver;
 
@@ -291,12 +285,19 @@
 
         mRingerModeAffectedStreams = Settings.System.getInt(cr,
                 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
-                ((1 << AudioManager.STREAM_RING)|(1 << AudioManager.STREAM_NOTIFICATION)|(1 << AudioManager.STREAM_SYSTEM)));
+                ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
+                 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)));
 
         mMuteAffectedStreams = System.getInt(cr,
                 System.MUTE_STREAMS_AFFECTED,
                 ((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM)));
 
+        mNotificationsUseRingVolume = System.getInt(cr,
+                Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1);
+
+        if (mNotificationsUseRingVolume == 1) {
+            STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING;
+        }
         // Each stream will read its own persisted settings
 
         // Broadcast the sticky intent
@@ -307,25 +308,13 @@
         broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
     }
 
-    private void readAudioSettings() {
-        synchronized (mSettingsLock) {
-            mMicMute = AudioSystem.isMicrophoneMuted();
-            mMode = AudioSystem.getMode();
-            for (int mode = 0; mode < AudioSystem.NUM_MODES; mode++) {
-                mRoutes[mode] = AudioSystem.getRouting(mode);
-            }
-        }
+    private void setStreamVolumeIndex(int stream, int index) {
+        AudioSystem.setStreamVolumeIndex(stream, (index + 5)/10);
     }
 
-    private void applyAudioSettings() {
-        synchronized (mSettingsLock) {
-            AudioSystem.muteMicrophone(mMicMute);
-            AudioSystem.setMode(mMode);
-            for (int mode = 0; mode < AudioSystem.NUM_MODES; mode++) {
-                AudioSystem.setRouting(mode, mRoutes[mode], AudioSystem.ROUTE_ALL);
-            }
-        }
-   }
+    private int rescaleIndex(int index, int srcStream, int dstStream) {
+        return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex();
+    }
 
     ///////////////////////////////////////////////////////////////////////////
     // IPC methods
@@ -354,44 +343,26 @@
         ensureValidDirection(direction);
         ensureValidStreamType(streamType);
 
-        boolean notificationsUseRingVolume = Settings.System.getInt(mContentResolver,
-                Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1) == 1;
-        if (notificationsUseRingVolume && streamType == AudioManager.STREAM_NOTIFICATION) {
-            // Redirect the volume change to the ring stream
-            streamType = AudioManager.STREAM_RING;
-        }
 
-        VolumeStreamState streamState = mStreamStates[streamType];
+        VolumeStreamState streamState = mStreamStates[STREAM_VOLUME_ALIAS[streamType]];
         final int oldIndex = streamState.mIndex;
         boolean adjustVolume = true;
 
         // If either the client forces allowing ringer modes for this adjustment,
         // or the stream type is one that is affected by ringer modes
         if ((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0
-                || streamType == AudioManager.STREAM_RING) {
+                || streamType == AudioSystem.STREAM_RING) {
             // Check if the ringer mode changes with this volume adjustment. If
             // it does, it will handle adjusting the volume, so we won't below
             adjustVolume = checkForRingerModeChange(oldIndex, direction);
         }
 
         if (adjustVolume && streamState.adjustIndex(direction)) {
-
-            boolean alsoUpdateNotificationVolume =  notificationsUseRingVolume &&
-                    streamType == AudioManager.STREAM_RING;
-            if (alsoUpdateNotificationVolume) {
-                mStreamStates[AudioManager.STREAM_NOTIFICATION].adjustIndex(direction);
-            }
-
             // Post message to set system volume (it in turn will post a message
             // to persist). Do not change volume if stream is muted.
             if (streamState.muteCount() == 0) {
-                sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, streamType, SENDMSG_NOOP, 0, 0,
+                sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, STREAM_VOLUME_ALIAS[streamType], SENDMSG_NOOP, 0, 0,
                         streamState, 0);
-
-                if (alsoUpdateNotificationVolume) {
-                    sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, AudioManager.STREAM_NOTIFICATION,
-                            SENDMSG_NOOP, 0, 0, mStreamStates[AudioManager.STREAM_NOTIFICATION], 0);
-                }
             }
         }
 
@@ -404,9 +375,8 @@
     /** @see AudioManager#setStreamVolume(int, int, int) */
     public void setStreamVolume(int streamType, int index, int flags) {
         ensureValidStreamType(streamType);
-        syncRingerAndNotificationStreamVolume(streamType, index, false);
-
-        setStreamVolumeInt(streamType, index, false, true);
+        index = rescaleIndex(index * 10, streamType, STREAM_VOLUME_ALIAS[streamType]);
+        setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, false, true);
 
         // UI, etc.
         mVolumePanel.postVolumeChanged(streamType, flags);
@@ -420,37 +390,12 @@
         intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, getStreamVolume(streamType));
 
         // Currently, sending the intent only when the stream is BLUETOOTH_SCO
-        if (streamType == AudioManager.STREAM_BLUETOOTH_SCO) {
+        if (streamType == AudioSystem.STREAM_BLUETOOTH_SCO) {
             mContext.sendBroadcast(intent);
         }
     }
 
     /**
-     * Sync the STREAM_RING and STREAM_NOTIFICATION volumes if mandated by the
-     * value in Settings.
-     *
-     * @param streamType Type of the stream
-     * @param index Volume index for the stream
-     * @param force If true, set the volume even if the current and desired
-     * volume as same
-     */
-    private void syncRingerAndNotificationStreamVolume(int streamType, int index, boolean force) {
-        boolean notificationsUseRingVolume = Settings.System.getInt(mContentResolver,
-                Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1) == 1;
-        if (notificationsUseRingVolume) {
-            if (streamType == AudioManager.STREAM_NOTIFICATION) {
-                // Redirect the volume change to the ring stream
-                streamType = AudioManager.STREAM_RING;
-            }
-            if (streamType == AudioManager.STREAM_RING) {
-                // One-off to sync notification volume to ringer volume
-                setStreamVolumeInt(AudioManager.STREAM_NOTIFICATION, index, force, true);
-            }
-        }
-    }
-
-
-    /**
      * Sets the stream state's index, and posts a message to set system volume.
      * This will not call out to the UI. Assumes a valid stream type.
      *
@@ -491,13 +436,13 @@
     /** @see AudioManager#getStreamVolume(int) */
     public int getStreamVolume(int streamType) {
         ensureValidStreamType(streamType);
-        return mStreamStates[streamType].mIndex;
+        return (mStreamStates[streamType].mIndex + 5) / 10;
     }
 
     /** @see AudioManager#getStreamMaxVolume(int) */
     public int getStreamMaxVolume(int streamType) {
         ensureValidStreamType(streamType);
-        return mStreamStates[streamType].getMaxIndex();
+        return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
     }
 
     /** @see AudioManager#getRingerMode() */
@@ -507,11 +452,12 @@
 
     /** @see AudioManager#setRingerMode(int) */
     public void setRingerMode(int ringerMode) {
-        if (ringerMode != mRingerMode) {
-            setRingerModeInt(ringerMode, true);
-
-            // Send sticky broadcast
-            broadcastRingerMode();
+        synchronized (mSettingsLock) {
+            if (ringerMode != mRingerMode) {
+                setRingerModeInt(ringerMode, true);
+                // Send sticky broadcast
+                broadcastRingerMode();
+            }
         }
     }
 
@@ -541,7 +487,7 @@
                 }
             }
         }
-        
+
         // Post a persist ringer mode msg
         if (persist) {
             sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG,
@@ -606,39 +552,28 @@
         return existingValue;
     }
 
-    /** @see AudioManager#setMicrophoneMute(boolean) */
-    public void setMicrophoneMute(boolean on) {
-        if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
-            return;
-        }
-        synchronized (mSettingsLock) {
-            if (on != mMicMute) {
-                AudioSystem.muteMicrophone(on);
-                mMicMute = on;
-            }
-        }
-    }
-
-    /** @see AudioManager#isMicrophoneMute() */
-    public boolean isMicrophoneMute() {
-        return mMicMute;
-    }
-
     /** @see AudioManager#setMode(int) */
     public void setMode(int mode) {
         if (!checkAudioSettingsPermission("setMode()")) {
             return;
         }
+
+        if (mode < AudioSystem.MODE_CURRENT || mode > AudioSystem.MODE_IN_CALL) {
+            return;
+        }
+
         synchronized (mSettingsLock) {
+            if (mode == AudioSystem.MODE_CURRENT) {
+                mode = mMode;
+            }
             if (mode != mMode) {
-                if (AudioSystem.setMode(mode) == AudioSystem.AUDIO_STATUS_OK) {
+                if (AudioSystem.setPhoneState(mode) == AudioSystem.AUDIO_STATUS_OK) {
                     mMode = mode;
                 }
             }
             int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
-            int index = mStreamStates[streamType].mIndex;
-            syncRingerAndNotificationStreamVolume(streamType, index, true);
-            setStreamVolumeInt(streamType, index, true, true);
+            int index = mStreamStates[STREAM_VOLUME_ALIAS[streamType]].mIndex;
+            setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, true, true);
         }
     }
 
@@ -647,187 +582,6 @@
         return mMode;
     }
 
-    /** @see AudioManager#setRouting(int, int, int) */
-    public void setRouting(int mode, int routes, int mask) {
-        int incallMask = 0;
-        int ringtoneMask = 0;
-        int normalMask = 0;
-
-        if (!checkAudioSettingsPermission("setRouting()")) {
-            return;
-        }
-        synchronized (mSettingsLock) {
-            // Temporary fix for issue #1713090 until audio routing is refactored in eclair release.
-            // mode AudioSystem.MODE_INVALID is used only by the following AudioManager methods:
-            // setWiredHeadsetOn(), setBluetoothA2dpOn(), setBluetoothScoOn() and setSpeakerphoneOn().
-            // If applications are using AudioManager.setRouting() that is now deprecated, the routing
-            // command will be ignored.
-            if (mode == AudioSystem.MODE_INVALID) {
-                switch (mask) {
-                case AudioSystem.ROUTE_SPEAKER:
-                    // handle setSpeakerphoneOn()
-                    if (routes != 0 && !mSpeakerIsOn) {
-                        mSpeakerIsOn = true;
-                        mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_SPEAKER;
-                        incallMask = AudioSystem.ROUTE_ALL;
-                    } else if (routes == 0 && mSpeakerIsOn) {
-                        mSpeakerIsOn = false;
-                        if (mBluetoothScoIsConnected) {
-                            mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_BLUETOOTH_SCO;
-                        } else if (mHeadsetIsConnected) {
-                            mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_HEADSET;
-                        } else {
-                            mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_EARPIECE;
-                        }
-                        incallMask = AudioSystem.ROUTE_ALL;
-                    }
-                    break;
-
-                case AudioSystem.ROUTE_BLUETOOTH_SCO:
-                    // handle setBluetoothScoOn()
-                    if (routes != 0 && !mBluetoothScoIsConnected) {
-                        mBluetoothScoIsConnected = true;
-                        mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_BLUETOOTH_SCO;
-                        mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) |
-                                                              AudioSystem.ROUTE_BLUETOOTH_SCO;
-                        mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) |
-                                                            AudioSystem.ROUTE_BLUETOOTH_SCO;
-                        incallMask = AudioSystem.ROUTE_ALL;
-                        // A2DP has higher priority than SCO headset, so headset connect/disconnect events
-                        // should not affect A2DP routing
-                        ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                        normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                    } else if (routes == 0 && mBluetoothScoIsConnected) {
-                        mBluetoothScoIsConnected = false;
-                        if (mHeadsetIsConnected) {
-                            mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_HEADSET;
-                            mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) |
-                                                                 (AudioSystem.ROUTE_HEADSET|AudioSystem.ROUTE_SPEAKER);
-                            mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) |
-                                                               AudioSystem.ROUTE_HEADSET;
-                        } else {
-                            if (mSpeakerIsOn) {
-                                mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_SPEAKER;
-                            } else {
-                                mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_EARPIECE;
-                            }
-                            mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) |
-                                                                 AudioSystem.ROUTE_SPEAKER;
-                            mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) |
-                                                               AudioSystem.ROUTE_SPEAKER;
-                        }
-                        incallMask = AudioSystem.ROUTE_ALL;
-                        // A2DP has higher priority than SCO headset, so headset connect/disconnect events
-                        // should not affect A2DP routing
-                        ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                        normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                    }
-                    break;
-
-                case AudioSystem.ROUTE_HEADSET:
-                    // handle setWiredHeadsetOn()
-                    if (routes != 0 && !mHeadsetIsConnected) {
-                        mHeadsetIsConnected = true;
-                        // do not act upon headset connection if bluetooth SCO is connected to match phone app behavior
-                        if (!mBluetoothScoIsConnected) {
-                            mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_HEADSET;
-                            mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) |
-                                                                 (AudioSystem.ROUTE_HEADSET|AudioSystem.ROUTE_SPEAKER);
-                            mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) |
-                                                               AudioSystem.ROUTE_HEADSET;
-                            incallMask = AudioSystem.ROUTE_ALL;
-                            // A2DP has higher priority than wired headset, so headset connect/disconnect events
-                            // should not affect A2DP routing
-                            ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                            normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                        }
-                    } else if (routes == 0 && mHeadsetIsConnected) {
-                        mHeadsetIsConnected = false;
-                        // do not act upon headset disconnection if bluetooth SCO is connected to match phone app behavior
-                        if (!mBluetoothScoIsConnected) {
-                            if (mSpeakerIsOn) {
-                                mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_SPEAKER;
-                            } else {
-                                mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_EARPIECE;
-                            }
-                            mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) |
-                                                                 AudioSystem.ROUTE_SPEAKER;
-                            mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) |
-                                                               AudioSystem.ROUTE_SPEAKER;
-
-                            incallMask = AudioSystem.ROUTE_ALL;
-                            // A2DP has higher priority than wired headset, so headset connect/disconnect events
-                            // should not affect A2DP routing
-                            ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                            normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                        }
-                    }
-                    break;
-
-                case AudioSystem.ROUTE_BLUETOOTH_A2DP:
-                    // handle setBluetoothA2dpOn()
-                    if (routes != 0 && !mBluetoothA2dpIsConnected) {
-                        mBluetoothA2dpIsConnected = true;
-                        mRoutes[AudioSystem.MODE_RINGTONE] |= AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                        mRoutes[AudioSystem.MODE_NORMAL] |= AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                        // the audio flinger chooses A2DP as a higher priority,
-                        // so there is no need to disable other routes.
-                        ringtoneMask = AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                        normalMask = AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                    } else if (routes == 0 && mBluetoothA2dpIsConnected) {
-                        mBluetoothA2dpIsConnected = false;
-                        mRoutes[AudioSystem.MODE_RINGTONE] &= ~AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                        mRoutes[AudioSystem.MODE_NORMAL] &= ~AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                        // the audio flinger chooses A2DP as a higher priority,
-                        // so there is no need to disable other routes.
-                        ringtoneMask = AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                        normalMask = AudioSystem.ROUTE_BLUETOOTH_A2DP;
-                    }
-                    break;
-                }
-                
-                // incallMask is != 0 means we must apply ne routing to MODE_IN_CALL mode
-                if (incallMask != 0) {
-                    AudioSystem.setRouting(AudioSystem.MODE_IN_CALL,
-                                           mRoutes[AudioSystem.MODE_IN_CALL],
-                                           incallMask);
-                }
-                // ringtoneMask is != 0 means we must apply ne routing to MODE_RINGTONE mode
-                if (ringtoneMask != 0) {
-                    AudioSystem.setRouting(AudioSystem.MODE_RINGTONE,
-                                           mRoutes[AudioSystem.MODE_RINGTONE],
-                                           ringtoneMask);
-                }
-                // normalMask is != 0 means we must apply ne routing to MODE_NORMAL mode
-                if (normalMask != 0) {
-                    AudioSystem.setRouting(AudioSystem.MODE_NORMAL,
-                                           mRoutes[AudioSystem.MODE_NORMAL],
-                                           normalMask);
-                }
-
-                int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
-                int index = mStreamStates[streamType].mIndex;
-                syncRingerAndNotificationStreamVolume(streamType, index, true);
-                setStreamVolumeInt(streamType, index, true, true);
-            }
-        }
-    }
-
-    /** @see AudioManager#getRouting(int) */
-    public int getRouting(int mode) {
-        return mRoutes[mode];
-    }
-
-    /** @see AudioManager#isMusicActive() */
-    public boolean isMusicActive() {
-        return AudioSystem.isMusicActive();
-    }
-
-    /** @see AudioManager#setParameter(String, String) */
-    public void setParameter(String key, String value) {
-        AudioSystem.setParameter(key, value);
-    }
-
     /** @see AudioManager#playSoundEffect(int) */
     public void playSoundEffect(int effectType) {
         sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SHARED_MSG, SENDMSG_NOOP,
@@ -926,18 +680,29 @@
         for (int streamType = 0; streamType < numStreamTypes; streamType++) {
             VolumeStreamState streamState = mStreamStates[streamType];
 
-            // there is no volume setting for STREAM_BLUETOOTH_SCO
-            if (streamType != AudioSystem.STREAM_BLUETOOTH_SCO) {
-                String settingName = System.VOLUME_SETTINGS[streamType];
-                String lastAudibleSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE;
-
-                streamState.mIndex = streamState.getValidIndex(Settings.System.getInt(mContentResolver,
-                        settingName,
-                        AudioManager.DEFAULT_STREAM_VOLUME[streamType]));
-                streamState.mLastAudibleIndex = streamState.getValidIndex(Settings.System.getInt(mContentResolver,
-                        lastAudibleSettingName,
-                        streamState.mIndex > 0 ? streamState.mIndex : AudioManager.DEFAULT_STREAM_VOLUME[streamType]));
+            String settingName = System.VOLUME_SETTINGS[STREAM_VOLUME_ALIAS[streamType]];
+            String lastAudibleSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE;
+            int index = Settings.System.getInt(mContentResolver,
+                                           settingName,
+                                           AudioManager.DEFAULT_STREAM_VOLUME[streamType]);
+            if (STREAM_VOLUME_ALIAS[streamType] != streamType) {
+                index = rescaleIndex(index * 10, STREAM_VOLUME_ALIAS[streamType], streamType);
+            } else {
+                index *= 10;
             }
+            streamState.mIndex = streamState.getValidIndex(index);
+
+            index = (index + 5) / 10;
+            index = Settings.System.getInt(mContentResolver,
+                                            lastAudibleSettingName,
+                                            (index > 0) ? index : AudioManager.DEFAULT_STREAM_VOLUME[streamType]);
+            if (STREAM_VOLUME_ALIAS[streamType] != streamType) {
+                index = rescaleIndex(index * 10, STREAM_VOLUME_ALIAS[streamType], streamType);
+            } else {
+                index *= 10;
+            }
+            streamState.mLastAudibleIndex = streamState.getValidIndex(index);
+
             // unmute stream that whas muted but is not affect by mute anymore
             if (streamState.muteCount() != 0 && !isStreamAffectedByMute(streamType)) {
                 int size = streamState.mDeathHandlers.size();
@@ -948,7 +713,7 @@
             }
             // apply stream volume
             if (streamState.muteCount() == 0) {
-                AudioSystem.setVolume(streamType, streamState.mVolumes[streamState.mIndex]);
+                setStreamVolumeIndex(streamType, streamState.mIndex);
             }
         }
 
@@ -969,7 +734,7 @@
         boolean adjustVolumeIndex = true;
         int newRingerMode = mRingerMode;
 
-        if (mRingerMode == AudioManager.RINGER_MODE_NORMAL && oldIndex == 1
+        if (mRingerMode == AudioManager.RINGER_MODE_NORMAL && (oldIndex + 5) / 10 == 1
                 && direction == AudioManager.ADJUST_LOWER) {
             newRingerMode = AudioManager.RINGER_MODE_VIBRATE;
         } else if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
@@ -1026,7 +791,7 @@
             Log.w(TAG, "Couldn't connect to phone service", e);
         }
 
-        if ((getRouting(AudioSystem.MODE_IN_CALL) & AudioSystem.ROUTE_BLUETOOTH_SCO) != 0) {
+        if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) == AudioSystem.FORCE_BT_SCO) {
             // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
             return AudioSystem.STREAM_BLUETOOTH_SCO;
         } else if (isOffhook) {
@@ -1110,47 +875,36 @@
         private final String mLastAudibleVolumeIndexSettingName;
         private final int mStreamType;
 
-        private final int[] mVolumes;
+        private int mIndexMax;
         private int mIndex;
         private int mLastAudibleIndex;
         private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo requests client death
 
-        private VolumeStreamState(String settingName, int streamType, int[] volumes) {
+        private VolumeStreamState(String settingName, int streamType) {
 
             mVolumeIndexSettingName = settingName;
             mLastAudibleVolumeIndexSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE;
 
             mStreamType = streamType;
-            mVolumes = volumes;
 
             final ContentResolver cr = mContentResolver;
-            mIndex = getValidIndex(Settings.System.getInt(cr, mVolumeIndexSettingName, AudioManager.DEFAULT_STREAM_VOLUME[streamType]));
-            mLastAudibleIndex = getValidIndex(Settings.System.getInt(cr,
-                    mLastAudibleVolumeIndexSettingName, mIndex > 0 ? mIndex : AudioManager.DEFAULT_STREAM_VOLUME[streamType]));
-
-            AudioSystem.setVolume(streamType, volumes[mIndex]);
-            mDeathHandlers = new ArrayList<VolumeDeathHandler>();
-        }
-
-        /**
-         * Constructor to be used when there is no setting associated with the VolumeStreamState.
-         *
-         * @param defaultVolume Default volume of the stream to use.
-         * @param streamType Type of the stream.
-         * @param volumes Volumes levels associated with this stream.
-         */
-        private VolumeStreamState(int defaultVolume, int streamType, int[] volumes) {
-            mVolumeIndexSettingName = null;
-            mLastAudibleVolumeIndexSettingName = null;
-            mIndex = mLastAudibleIndex = defaultVolume;
-            mStreamType = streamType;
-            mVolumes = volumes;
-            AudioSystem.setVolume(mStreamType, defaultVolume);
+            mIndexMax = AudioManager.MAX_STREAM_VOLUME[streamType];
+            mIndex = Settings.System.getInt(cr,
+                                            mVolumeIndexSettingName,
+                                            AudioManager.DEFAULT_STREAM_VOLUME[streamType]);
+            mLastAudibleIndex = Settings.System.getInt(cr,
+                                                       mLastAudibleVolumeIndexSettingName,
+                                                       (mIndex > 0) ? mIndex : AudioManager.DEFAULT_STREAM_VOLUME[streamType]);
+            AudioSystem.initStreamVolume(streamType, 0, mIndexMax);
+            mIndexMax *= 10;
+            mIndex = getValidIndex(10 * mIndex);
+            mLastAudibleIndex = getValidIndex(10 * mLastAudibleIndex);
+            setStreamVolumeIndex(streamType, mIndex);
             mDeathHandlers = new ArrayList<VolumeDeathHandler>();
         }
 
         public boolean adjustIndex(int deltaIndex) {
-            return setIndex(mIndex + deltaIndex, true);
+            return setIndex(mIndex + deltaIndex * 10, true);
         }
 
         public boolean setIndex(int index, boolean lastAudible) {
@@ -1161,6 +915,13 @@
                 if (lastAudible) {
                     mLastAudibleIndex = mIndex;
                 }
+                // Apply change to all streams using this one as alias
+                int numStreamTypes = AudioSystem.getNumStreamTypes();
+                for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+                    if (streamType != mStreamType && STREAM_VOLUME_ALIAS[streamType] == mStreamType) {
+                        mStreamStates[streamType].setIndex(rescaleIndex(mIndex, mStreamType, streamType), lastAudible);
+                    }
+                }
                 return true;
             } else {
                 return false;
@@ -1168,7 +929,7 @@
         }
 
         public int getMaxIndex() {
-            return mVolumes.length - 1;
+            return mIndexMax;
         }
 
         public void mute(IBinder cb, boolean state) {
@@ -1183,8 +944,8 @@
         private int getValidIndex(int index) {
             if (index < 0) {
                 return 0;
-            } else if (index >= mVolumes.length) {
-                return mVolumes.length - 1;
+            } else if (index > mIndexMax) {
+                return mIndexMax;
             }
 
             return index;
@@ -1318,8 +1079,16 @@
         private void setSystemVolume(VolumeStreamState streamState) {
 
             // Adjust volume
-            AudioSystem
-                    .setVolume(streamState.mStreamType, streamState.mVolumes[streamState.mIndex]);
+            setStreamVolumeIndex(streamState.mStreamType, streamState.mIndex);
+
+            // Apply change to all streams using this one as alias
+            int numStreamTypes = AudioSystem.getNumStreamTypes();
+            for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+                if (streamType != streamState.mStreamType &&
+                    STREAM_VOLUME_ALIAS[streamType] == streamState.mStreamType) {
+                    setStreamVolumeIndex(streamType, mStreamStates[streamType].mIndex);
+                }
+            }
 
             // Post a persist volume msg
             sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, streamState.mStreamType,
@@ -1327,12 +1096,10 @@
         }
 
         private void persistVolume(VolumeStreamState streamState) {
-            if (streamState.mStreamType != AudioManager.STREAM_BLUETOOTH_SCO) {
-                System.putInt(mContentResolver, streamState.mVolumeIndexSettingName,
-                        streamState.mIndex);
-                System.putInt(mContentResolver, streamState.mLastAudibleVolumeIndexSettingName,
-                        streamState.mLastAudibleIndex);
-            }
+            System.putInt(mContentResolver, streamState.mVolumeIndexSettingName,
+                    (streamState.mIndex + 5)/ 10);
+            System.putInt(mContentResolver, streamState.mLastAudibleVolumeIndexSettingName,
+                    (streamState.mLastAudibleIndex + 5) / 10);
         }
 
         private void persistRingerMode() {
@@ -1426,18 +1193,17 @@
 
                 case MSG_MEDIA_SERVER_STARTED:
                     Log.e(TAG, "Media server started.");
-                    // Restore audio routing and stream volumes
-                    applyAudioSettings();
+                    // Restore stream volumes
                     int numStreamTypes = AudioSystem.getNumStreamTypes();
                     for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
-                        int volume;
+                        int index;
                         VolumeStreamState streamState = mStreamStates[streamType];
                         if (streamState.muteCount() == 0) {
-                            volume = streamState.mVolumes[streamState.mIndex];
+                            index = streamState.mIndex;
                         } else {
-                            volume = streamState.mVolumes[0];
+                            index = 0;
                         }
-                        AudioSystem.setVolume(streamType, volume);
+                        setStreamVolumeIndex(streamType, index);
                     }
                     setRingerMode(mRingerMode);
                     mMediaServerOk = true;
@@ -1451,28 +1217,144 @@
     }
 
     private class SettingsObserver extends ContentObserver {
-        
+
         SettingsObserver() {
             super(new Handler());
             mContentResolver.registerContentObserver(Settings.System.getUriFor(
                 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
+            mContentResolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.NOTIFICATIONS_USE_RING_VOLUME), false, this);
         }
 
         @Override
         public void onChange(boolean selfChange) {
             super.onChange(selfChange);
-            
-            mRingerModeAffectedStreams = Settings.System.getInt(mContentResolver,
-                    Settings.System.MODE_RINGER_STREAMS_AFFECTED,
-                    0);
+            synchronized (mSettingsLock) {
+                int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver,
+                        Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+                        0);
+                if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
+                    /*
+                     * Ensure all stream types that should be affected by ringer mode
+                     * are in the proper state.
+                     */
+                    mRingerModeAffectedStreams = ringerModeAffectedStreams;
+                    setRingerModeInt(getRingerMode(), false);
+                }
 
-            /*
-             * Ensure all stream types that should be affected by ringer mode
-             * are in the proper state.
-             */
-            setRingerModeInt(getRingerMode(), false);
+                int notificationsUseRingVolume = Settings.System.getInt(mContentResolver,
+                        Settings.System.NOTIFICATIONS_USE_RING_VOLUME,
+                        1);
+                if (notificationsUseRingVolume != mNotificationsUseRingVolume) {
+                    mNotificationsUseRingVolume = notificationsUseRingVolume;
+                    if (mNotificationsUseRingVolume == 1) {
+                        STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING;
+                    } else {
+                        STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_NOTIFICATION;
+                        // Persist notification volume volume as it was not persisted while aliased to ring volume
+                        sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, AudioSystem.STREAM_NOTIFICATION,
+                                SENDMSG_REPLACE, 0, 0, mStreamStates[AudioSystem.STREAM_NOTIFICATION], PERSIST_DELAY);
+                    }
+                }
+            }
         }
-        
     }
-    
+
+    /**
+     * Receiver for misc intent broadcasts the Phone app cares about.
+     */
+    private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+
+            if (action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
+                int state = intent.getIntExtra(BluetoothA2dp.SINK_STATE,
+                                               BluetoothA2dp.STATE_DISCONNECTED);
+                String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
+                if (state == BluetoothA2dp.STATE_DISCONNECTED) {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+                            AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                            address);
+                } else if (state == BluetoothA2dp.STATE_CONNECTED){
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+                                                         AudioSystem.DEVICE_STATE_AVAILABLE,
+                                                         address);
+                }
+            } else if (action.equals(BluetoothIntent.HEADSET_AUDIO_STATE_CHANGED_ACTION)) {
+                int state = intent.getIntExtra(BluetoothIntent.HEADSET_AUDIO_STATE,
+                                               BluetoothHeadset.STATE_ERROR);
+                String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
+                if (state == BluetoothHeadset.AUDIO_STATE_DISCONNECTED) {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
+                                                         AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                                                         address);
+                } else if (state == BluetoothHeadset.AUDIO_STATE_CONNECTED) {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
+                                                         AudioSystem.DEVICE_STATE_AVAILABLE,
+                                                         address);
+                }
+            } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
+                int state = intent.getIntExtra("state", 0);
+                if ((state & BIT_HEADSET) == 0 &&
+                    (mHeadsetState & BIT_HEADSET) != 0) {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
+                            AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                            "");
+                } else if ((state & BIT_HEADSET) != 0 &&
+                    (mHeadsetState & BIT_HEADSET) == 0)  {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
+                            AudioSystem.DEVICE_STATE_AVAILABLE,
+                            "");
+                }
+                if ((state & BIT_HEADSET_NO_MIC) == 0 &&
+                    (mHeadsetState & BIT_HEADSET_NO_MIC) != 0) {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
+                            AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                            "");
+                } else if ((state & BIT_HEADSET_NO_MIC) != 0 &&
+                    (mHeadsetState & BIT_HEADSET_NO_MIC) == 0)  {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
+                            AudioSystem.DEVICE_STATE_AVAILABLE,
+                            "");
+                }
+                if ((state & BIT_TTY) == 0 &&
+                    (mHeadsetState & BIT_TTY) != 0) {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_TTY,
+                            AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                            "");
+                } else if ((state & BIT_TTY) != 0 &&
+                    (mHeadsetState & BIT_TTY) == 0)  {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_TTY,
+                            AudioSystem.DEVICE_STATE_AVAILABLE,
+                            "");
+                }
+                if ((state & BIT_FM_HEADSET) == 0 &&
+                    (mHeadsetState & BIT_FM_HEADSET) != 0) {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_HEADPHONE,
+                            AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                            "");
+                } else if ((state & BIT_FM_HEADSET) != 0 &&
+                    (mHeadsetState & BIT_FM_HEADSET) == 0)  {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_HEADPHONE,
+                            AudioSystem.DEVICE_STATE_AVAILABLE,
+                            "");
+                }
+                if ((state & BIT_FM_SPEAKER) == 0 &&
+                    (mHeadsetState & BIT_FM_SPEAKER) != 0) {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_SPEAKER,
+                            AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                            "");
+                } else if ((state & BIT_FM_SPEAKER) != 0 &&
+                    (mHeadsetState & BIT_FM_SPEAKER) == 0)  {
+                    AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_SPEAKER,
+                            AudioSystem.DEVICE_STATE_AVAILABLE,
+                            "");
+                }
+                mHeadsetState = state;
+            }
+        }
+    }
+
+
 }
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 5917ab90..d587f65 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -45,38 +45,21 @@
     public static final int STREAM_NOTIFICATION = 5;
     /* @hide The audio stream for phone calls when connected on bluetooth */
     public static final int STREAM_BLUETOOTH_SCO = 6;
+    /* @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */
+    public static final int STREAM_SYSTEM_ENFORCED = 7;
+    /* @hide The audio stream for DTMF tones */
+    public static final int STREAM_DTMF = 8;
+    /* @hide The audio stream for text to speech (TTS) */
+    public static final int STREAM_TTS = 9;
     /**
      * @deprecated Use {@link #numStreamTypes() instead}
      */
     public static final int NUM_STREAMS = 5;
 
     // Expose only the getter method publicly so we can change it in the future
-    private static final int NUM_STREAM_TYPES = 7;
+    private static final int NUM_STREAM_TYPES = 10;
     public static final int getNumStreamTypes() { return NUM_STREAM_TYPES; }
 
-    /* max and min volume levels */
-    /* Maximum volume setting, for use with setVolume(int,int) */
-    public static final int MAX_VOLUME = 100;
-    /* Minimum volume setting, for use with setVolume(int,int) */
-    public static final int MIN_VOLUME = 0;
-
-    /*
-     * Sets the volume of a specified audio stream.
-     *
-     * param type   the stream type to set the volume of (e.g. STREAM_MUSIC)
-     * param volume the volume level to set (0-100)
-     * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR
-     */
-    public static native int setVolume(int type, int volume);
-
-    /*
-     * Returns the volume of a specified audio stream.
-     *
-     * param type the stream type to get the volume of (e.g. STREAM_MUSIC)
-     * return the current volume (0-100)
-     */
-    public static native int getVolume(int type);
-
     /*
      * Sets the microphone mute on or off.
      *
@@ -101,17 +84,22 @@
      *              it can route the audio appropriately.
      * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR
      */
-    public static native int setMode(int mode);
-
+    /** @deprecated use {@link #setPhoneState(int)} */
+    public static int setMode(int mode) {
+        return AUDIO_STATUS_ERROR;
+    }
     /*
      * Returns the current audio mode.
      *
      * return      the current audio mode (NORMAL, RINGTONE, or IN_CALL).
      *              Returns the current current audio state from the HAL.
      */
-    public static native int getMode();
+    /** @deprecated */
+    public static int getMode() {
+        return MODE_INVALID;
+    }
 
-    /* modes for setMode/getMode/setRoute/getRoute */
+    /* modes for setPhoneState */
     public static final int MODE_INVALID            = -2;
     public static final int MODE_CURRENT            = -1;
     public static final int MODE_NORMAL             = 0;
@@ -121,15 +109,20 @@
 
 
     /* Routing bits for setRouting/getRouting API */
-    public static final int ROUTE_EARPIECE          = (1 << 0);
-    public static final int ROUTE_SPEAKER           = (1 << 1);
-
+    /** @deprecated */
+    @Deprecated public static final int ROUTE_EARPIECE          = (1 << 0);
+    /** @deprecated */
+    @Deprecated public static final int ROUTE_SPEAKER           = (1 << 1);
     /** @deprecated use {@link #ROUTE_BLUETOOTH_SCO} */
     @Deprecated public static final int ROUTE_BLUETOOTH = (1 << 2);
-    public static final int ROUTE_BLUETOOTH_SCO     = (1 << 2);
-    public static final int ROUTE_HEADSET           = (1 << 3);
-    public static final int ROUTE_BLUETOOTH_A2DP    = (1 << 4);
-    public static final int ROUTE_ALL               = 0xFFFFFFFF;
+    /** @deprecated */
+    @Deprecated public static final int ROUTE_BLUETOOTH_SCO     = (1 << 2);
+    /** @deprecated */
+    @Deprecated public static final int ROUTE_HEADSET           = (1 << 3);
+    /** @deprecated */
+    @Deprecated public static final int ROUTE_BLUETOOTH_A2DP    = (1 << 4);
+    /** @deprecated */
+    @Deprecated public static final int ROUTE_ALL               = 0xFFFFFFFF;
 
     /*
      * Sets the audio routing for a specified mode
@@ -141,7 +134,10 @@
      * ROUTE_xxx types. Unset bits indicate the route should be left unchanged
      * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR
      */
-    public static native int setRouting(int mode, int routes, int mask);
+    /** @deprecated use {@link #setDeviceConnectionState(int,int,String)} */
+    public static int setRouting(int mode, int routes, int mask) {
+        return AUDIO_STATUS_ERROR;
+    }
 
     /*
      * Returns the current audio routing bit vector for a specified mode.
@@ -150,7 +146,10 @@
      * return an audio route bit vector that can be compared with ROUTE_xxx
      * bits
      */
-    public static native int getRouting(int mode);
+    /** @deprecated use {@link #getDeviceConnectionState(int,String)} */
+    public static int getRouting(int mode) {
+        return 0;
+    }
 
     /*
      * Checks whether any music is active.
@@ -160,17 +159,23 @@
     public static native boolean isMusicActive();
 
     /*
-     * Sets a generic audio configuration parameter. The use of these parameters
+     * Sets a group generic audio configuration parameters. The use of these parameters
      * are platform dependant, see libaudio
      *
-     * ** Temporary interface - DO NOT USE
-     *
-     * TODO: Replace with a more generic key:value get/set mechanism
-     *
-     * param key   name of parameter to set. Must not be null.
-     * param value value of parameter. Must not be null.
+     * param keyValuePairs  list of parameters key value pairs in the form:
+     *    key1=value1;key2=value2;...
      */
-    public static native void setParameter(String key, String value);
+    public static native int setParameters(String keyValuePairs);
+
+    /*
+     * Gets a group generic audio configuration parameters. The use of these parameters
+     * are platform dependant, see libaudio
+     *
+     * param keys  list of parameters
+     * return value: list of parameters key value pairs in the form:
+     *    key1=value1;key2=value2;...
+     */
+    public static native String getParameters(String keys);
 
     /*
     private final static String TAG = "audio";
@@ -220,4 +225,68 @@
             mErrorCallback.onError(error);
         }
     }
+
+    /*
+     * AudioPolicyService methods
+     */
+
+    // output devices
+    public static final int DEVICE_OUT_EARPIECE = 0x1;
+    public static final int DEVICE_OUT_SPEAKER = 0x2;
+    public static final int DEVICE_OUT_WIRED_HEADSET = 0x4;
+    public static final int DEVICE_OUT_WIRED_HEADPHONE = 0x8;
+    public static final int DEVICE_OUT_BLUETOOTH_SCO = 0x10;
+    public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20;
+    public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40;
+    public static final int DEVICE_OUT_BLUETOOTH_A2DP = 0x80;
+    public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100;
+    public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200;
+    public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;
+    public static final int DEVICE_OUT_FM_HEADPHONE = 0x800;
+    public static final int DEVICE_OUT_FM_SPEAKER = 0x1000;
+    public static final int DEVICE_OUT_TTY = 0x2000;
+    public static final int DEVICE_OUT_DEFAULT = 0x8000;
+    // input devices
+    public static final int DEVICE_IN_COMMUNICATION = 0x10000;
+    public static final int DEVICE_IN_AMBIENT = 0x20000;
+    public static final int DEVICE_IN_BUILTIN_MIC1 = 0x40000;
+    public static final int DEVICE_IN_BUILTIN_MIC2 = 0x80000;
+    public static final int DEVICE_IN_MIC_ARRAY = 0x100000;
+    public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x200000;
+    public static final int DEVICE_IN_WIRED_HEADSET = 0x400000;
+    public static final int DEVICE_IN_AUX_DIGITAL = 0x800000;
+    public static final int DEVICE_IN_DEFAULT = 0x80000000;
+
+    // device states
+    public static final int DEVICE_STATE_UNAVAILABLE = 0;
+    public static final int DEVICE_STATE_AVAILABLE = 1;
+
+    // phone state
+    public static final int PHONE_STATE_OFFCALL = 0;
+    public static final int PHONE_STATE_RINGING = 1;
+    public static final int PHONE_STATE_INCALL = 2;
+
+    // config for setForceUse
+    public static final int FORCE_NONE = 0;
+    public static final int FORCE_SPEAKER = 1;
+    public static final int FORCE_HEADPHONES = 2;
+    public static final int FORCE_BT_SCO = 3;
+    public static final int FORCE_BT_A2DP = 4;
+    public static final int FORCE_WIRED_ACCESSORY = 5;
+    public static final int FORCE_DEFAULT = FORCE_NONE;
+
+    // usage for serForceUse
+    public static final int FOR_COMMUNICATION = 0;
+    public static final int FOR_MEDIA = 1;
+    public static final int FOR_RECORD = 2;
+
+    public static native int setDeviceConnectionState(int device, int state, String device_address);
+    public static native int getDeviceConnectionState(int device, String device_address);
+    public static native int setPhoneState(int state);
+    public static native int setRingerMode(int mode, int mask);
+    public static native int setForceUse(int usage, int config);
+    public static native int getForceUse(int usage);
+    public static native int initStreamVolume(int stream, int indexMin, int indexMax);
+    public static native int setStreamVolumeIndex(int stream, int index);
+    public static native int getStreamVolumeIndex(int stream);
 }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 5f1be9d..7fbe965 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -120,7 +120,7 @@
     public  static final int ERROR_INVALID_OPERATION               = -3;
 
     private static final int ERROR_NATIVESETUP_AUDIOSYSTEM         = -16;
-    private static final int ERROR_NATIVESETUP_INVALIDCHANNELCOUNT = -17;
+    private static final int ERROR_NATIVESETUP_INVALIDCHANNELMASK  = -17;
     private static final int ERROR_NATIVESETUP_INVALIDFORMAT       = -18;
     private static final int ERROR_NATIVESETUP_INVALIDSTREAMTYPE   = -19;
     private static final int ERROR_NATIVESETUP_NATIVEINITFAILED    = -20;
@@ -198,7 +198,7 @@
     /**
      * The current audio channel configuration.
      */
-    private int mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+    private int mChannelConfiguration = AudioFormat.CHANNEL_OUT_MONO;
     /**
      * The encoding of the audio samples.
      * @see AudioFormat#ENCODING_PCM_8BIT
@@ -235,8 +235,8 @@
      * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but
      *   not limited to) 44100, 22050 and 11025.
      * @param channelConfig describes the configuration of the audio channels.
-     *   See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and
-     *   {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
+     *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
+     *   {@link AudioFormat#CHANNEL_OUT_STEREO}
      * @param audioFormat the format in which the audio data is represented.
      *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
      *   {@link AudioFormat#ENCODING_PCM_8BIT}
@@ -298,7 +298,8 @@
            && (streamType != AudioManager.STREAM_RING) && (streamType != AudioManager.STREAM_SYSTEM)
            && (streamType != AudioManager.STREAM_VOICE_CALL)
            && (streamType != AudioManager.STREAM_NOTIFICATION)
-           && (streamType != AudioManager.STREAM_BLUETOOTH_SCO)) {
+           && (streamType != AudioManager.STREAM_BLUETOOTH_SCO)
+           && (streamType != AudioManager.STREAM_DTMF)) {
             throw (new IllegalArgumentException("Invalid stream type."));
         } else {
             mStreamType = streamType;
@@ -316,18 +317,18 @@
         //--------------
         // channel config
         switch (channelConfig) {
-        case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT:
-        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
+        case AudioFormat.CHANNEL_OUT_DEFAULT:
+        case AudioFormat.CHANNEL_OUT_MONO:
             mChannelCount = 1;
-            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+            mChannelConfiguration = AudioFormat.CHANNEL_OUT_MONO;
             break;
-        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
+        case AudioFormat.CHANNEL_OUT_STEREO:
             mChannelCount = 2;
-            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+            mChannelConfiguration = AudioFormat.CHANNEL_OUT_STEREO;
             break;
         default:
             mChannelCount = 0;
-            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_INVALID;
+            mChannelConfiguration = AudioFormat.CHANNEL_INVALID;
             throw(new IllegalArgumentException("Unsupported channel configuration."));
         }
 
@@ -452,8 +453,8 @@
     /**
      * Returns the configured channel configuration.
 
-     * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO}
-     * and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}.
+     * See {@link AudioFormat#CHANNEL_OUT_MONO}
+     * and {@link AudioFormat#CHANNEL_OUT_STEREO}.
      */
     public int getChannelConfiguration() {
         return mChannelConfiguration;
@@ -531,8 +532,8 @@
      * the expected frequency at which the buffer will be refilled with additional data to play. 
      * @param sampleRateInHz the sample rate expressed in Hertz.
      * @param channelConfig describes the configuration of the audio channels. 
-     *   See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and
-     *   {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
+     *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
+     *   {@link AudioFormat#CHANNEL_OUT_STEREO}
      * @param audioFormat the format in which the audio data is represented. 
      *   See {@link AudioFormat#ENCODING_PCM_16BIT} and 
      *   {@link AudioFormat#ENCODING_PCM_8BIT}
@@ -544,10 +545,10 @@
     static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
         int channelCount = 0;
         switch(channelConfig) {
-        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
+        case AudioFormat.CHANNEL_OUT_MONO:
             channelCount = 1;
             break;
-        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
+        case AudioFormat.CHANNEL_OUT_STEREO:
             channelCount = 2;
             break;
         default:
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 9a8264f..bb4252b 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -29,9 +29,9 @@
     
     void setStreamVolume(int streamType, int index, int flags);
     
-   	void setStreamSolo(int streamType, boolean state, IBinder cb);
+    void setStreamSolo(int streamType, boolean state, IBinder cb);
    	
-   	void setStreamMute(int streamType, boolean state, IBinder cb);
+    void setStreamMute(int streamType, boolean state, IBinder cb);
     
     int getStreamVolume(int streamType);
     
@@ -46,23 +46,11 @@
     int getVibrateSetting(int vibrateType);
     
     boolean shouldVibrate(int vibrateType);
-    
-    void setMicrophoneMute(boolean on);
-
-    boolean isMicrophoneMute();
 
     void setMode(int mode);
 
     int getMode();
 
-    void setRouting(int mode, int routes, int mask);
-
-    int getRouting(int mode);
-
-    boolean isMusicActive();
-
-    void setParameter(String key, String value);
-
     oneway void playSoundEffect(int effectType);
   
     oneway void playSoundEffectVolume(int effectType, float volume);
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index 4fb0ead..2263605 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -89,7 +89,7 @@
     // Jet rendering audio parameters
     private static final int JET_OUTPUT_RATE = 22050; // _SAMPLE_RATE_22050 in Android.mk
     private static final int JET_OUTPUT_CHANNEL_CONFIG =
-            AudioFormat.CHANNEL_CONFIGURATION_STEREO; // NUM_OUTPUT_CHANNELS=2 in Android.mk
+            AudioFormat.CHANNEL_OUT_STEREO; // NUM_OUTPUT_CHANNELS=2 in Android.mk
 
     
     //--------------------------------------------
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 8be11df..03ffc67 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -41,8 +41,9 @@
     public static final int FILE_TYPE_AWB     = 5;
     public static final int FILE_TYPE_WMA     = 6;
     public static final int FILE_TYPE_OGG     = 7;
+    public static final int FILE_TYPE_AAC     = 8;
     private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3;
-    private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_OGG;
+    private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_AAC;
 
     // MIDI file types
     public static final int FILE_TYPE_MID     = 11;
@@ -57,8 +58,9 @@
     public static final int FILE_TYPE_3GPP    = 23;
     public static final int FILE_TYPE_3GPP2   = 24;
     public static final int FILE_TYPE_WMV     = 25;
+    public static final int FILE_TYPE_ASF     = 26;
     private static final int FIRST_VIDEO_FILE_TYPE = FILE_TYPE_MP4;
-    private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_WMV;
+    private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_ASF;
     
     // Image file types
     public static final int FILE_TYPE_JPEG    = 31;
@@ -104,6 +106,7 @@
         addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma");    
         addFileType("OGG", FILE_TYPE_OGG, "application/ogg");
         addFileType("OGA", FILE_TYPE_OGG, "application/ogg");
+        addFileType("AAC", FILE_TYPE_AAC, "audio/aac");
  
         addFileType("MID", FILE_TYPE_MID, "audio/midi");
         addFileType("MIDI", FILE_TYPE_MID, "audio/midi");
@@ -121,6 +124,7 @@
         addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2");
         addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2");
         addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv");
+        addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf");
 
         addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg");
         addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg");
diff --git a/media/java/android/media/Metadata.java b/media/java/android/media/Metadata.java
index 70e89a2..bd25da2 100644
--- a/media/java/android/media/Metadata.java
+++ b/media/java/android/media/Metadata.java
@@ -104,7 +104,7 @@
     public static final int SEEK_FORWARD_AVAILABLE = 31;  // Boolean
 
     private static final int LAST_SYSTEM = 31;
-    private static final int FIRST_CUSTOM = 8092;
+    private static final int FIRST_CUSTOM = 8192;
 
     // Shorthands to set the MediaPlayer's metadata filter.
     public static final Set<Integer> MATCH_NONE = Collections.EMPTY_SET;
diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
index e5ee9a3..c60a1ac 100644
--- a/media/java/android/media/ToneGenerator.java
+++ b/media/java/android/media/ToneGenerator.java
@@ -724,9 +724,9 @@
     public static final int TONE_CDMA_SIGNAL_OFF = 98;
 
     /** Maximum volume, for use with {@link #ToneGenerator(int,int)} */
-    public static final int MAX_VOLUME = AudioSystem.MAX_VOLUME;
+    public static final int MAX_VOLUME = 100;
     /** Minimum volume setting, for use with {@link #ToneGenerator(int,int)} */
-    public static final int MIN_VOLUME = AudioSystem.MIN_VOLUME;
+    public static final int MIN_VOLUME = 0;
 
 
     /**
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index ce80f92..0d07abe 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -18,8 +18,7 @@
 #define LOG_TAG "SoundPool"
 #include <utils/Log.h>
 
-//
-#define USE_SHARED_MEM_BUFFER
+//#define USE_SHARED_MEM_BUFFER
 
 // XXX needed for timing latency
 #include <utils/Timers.h>
@@ -528,13 +527,14 @@
     // wrong audio audio buffer size  (mAudioBufferSize)
     unsigned long toggle = mToggle ^ 1;
     void *userData = (void *)((unsigned long)this | toggle);
+    uint32_t channels = (numChannels == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO;
     
 #ifdef USE_SHARED_MEM_BUFFER
     newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-            numChannels, sample->getIMemory(), 0, callback, userData);
+            channels, sample->getIMemory(), 0, callback, userData);
 #else
     newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-            numChannels, frameCount, 0, callback, userData, bufferFrames);
+            channels, frameCount, 0, callback, userData, bufferFrames);
 #endif
     if (newTrack->initCheck() != NO_ERROR) {
         LOGE("Error creating AudioTrack");
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index cdaab04..9d442c3 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -2,24 +2,26 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	AudioTrack.cpp \
-	IAudioFlinger.cpp \
-	IAudioFlingerClient.cpp \
-	IAudioTrack.cpp \
-	IAudioRecord.cpp \
-	AudioRecord.cpp \
-	AudioSystem.cpp \
-	mediaplayer.cpp \
-	IMediaPlayerService.cpp \
-	IMediaPlayerClient.cpp \
-	IMediaPlayer.cpp \
-	IMediaRecorder.cpp \
-	mediarecorder.cpp \
-	IMediaMetadataRetriever.cpp \
-	mediametadataretriever.cpp \
-	ToneGenerator.cpp \
-	JetPlayer.cpp \
-        IOMX.cpp
+    AudioTrack.cpp \
+    IAudioFlinger.cpp \
+    IAudioFlingerClient.cpp \
+    IAudioTrack.cpp \
+    IAudioRecord.cpp \
+    AudioRecord.cpp \
+    AudioSystem.cpp \
+    mediaplayer.cpp \
+    IMediaPlayerService.cpp \
+    IMediaPlayerClient.cpp \
+    IMediaPlayer.cpp \
+    IMediaRecorder.cpp \
+    Metadata.cpp \
+    mediarecorder.cpp \
+    IMediaMetadataRetriever.cpp \
+    mediametadataretriever.cpp \
+    ToneGenerator.cpp \
+    JetPlayer.cpp \
+    IOMX.cpp \
+ 	IAudioPolicyService.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 0a6f4f7..5e35564 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -28,6 +28,7 @@
 
 #include <media/AudioSystem.h>
 #include <media/AudioRecord.h>
+#include <media/mediarecorder.h>
 
 #include <binder/IServiceManager.h>
 #include <utils/Log.h>
@@ -45,7 +46,7 @@
 // ---------------------------------------------------------------------------
 
 AudioRecord::AudioRecord()
-    : mStatus(NO_INIT)
+    : mStatus(NO_INIT), mInput(0)
 {
 }
 
@@ -53,15 +54,15 @@
         int inputSource,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        uint32_t channels,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
         void* user,
         int notificationFrames)
-    : mStatus(NO_INIT)
+    : mStatus(NO_INIT), mInput(0)
 {
-    mStatus = set(inputSource, sampleRate, format, channelCount,
+    mStatus = set(inputSource, sampleRate, format, channels,
             frameCount, flags, cbf, user, notificationFrames);
 }
 
@@ -78,6 +79,7 @@
         }
         mAudioRecord.clear();
         IPCThreadState::self()->flushCommands();
+        AudioSystem::releaseInput(mInput);
     }
 }
 
@@ -85,7 +87,7 @@
         int inputSource,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        uint32_t channels,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -94,7 +96,7 @@
         bool threadCanCallJava)
 {
 
-    LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount);
+    LOGV("set(): sampleRate %d, channels %d, frameCount %d",sampleRate, channels, frameCount);
     if (mAudioRecord != 0) {
         return INVALID_OPERATION;
     }
@@ -104,8 +106,8 @@
         return NO_INIT;
     }
 
-    if (inputSource == DEFAULT_INPUT) {
-        inputSource = MIC_INPUT;
+    if (inputSource == AUDIO_SOURCE_DEFAULT) {
+        inputSource = AUDIO_SOURCE_MIC;
     }
 
     if (sampleRate == 0) {
@@ -115,15 +117,21 @@
     if (format == 0) {
         format = AudioSystem::PCM_16_BIT;
     }
-    if (channelCount == 0) {
-        channelCount = 1;
-    }
-
     // validate parameters
-    if (format != AudioSystem::PCM_16_BIT) {
+    if (!AudioSystem::isValidFormat(format)) {
+        LOGE("Invalid format");
         return BAD_VALUE;
     }
-    if (channelCount != 1 && channelCount != 2) {
+
+    if (!AudioSystem::isInputChannel(channels)) {
+        return BAD_VALUE;
+    }
+    int channelCount = AudioSystem::popCount(channels);
+
+    mInput = AudioSystem::getInput(inputSource,
+                                    sampleRate, format, channels, (AudioSystem::audio_in_acoustics)flags);
+    if (mInput == 0) {
+        LOGE("Could not get audio output for stream type %d", inputSource);
         return BAD_VALUE;
     }
 
@@ -132,14 +140,22 @@
     if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
             != NO_ERROR) {
         LOGE("AudioSystem could not query the input buffer size.");
-        return NO_INIT;    
+        return NO_INIT;
     }
+
     if (inputBuffSizeInBytes == 0) {
         LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
             sampleRate, channelCount, format);
         return BAD_VALUE;
     }
+
     int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
+    if (AudioSystem::isLinearPCM(format)) {
+        frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? sizeof(int16_t) : sizeof(int8_t));
+    } else {
+        frameSizeInBytes = sizeof(int8_t);
+    }
+
 
     // We use 2* size of input buffer for ping pong use of record buffer.
     int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
@@ -157,11 +173,11 @@
 
     // open record channel
     status_t status;
-    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), inputSource,
+    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput,
                                                        sampleRate, format,
                                                        channelCount,
                                                        frameCount,
-                                                       ((uint16_t)flags) << 16, 
+                                                       ((uint16_t)flags) << 16,
                                                        &status);
     if (record == 0) {
         LOGE("AudioFlinger could not create record track, status: %d", status);
@@ -188,7 +204,7 @@
     mFormat = format;
     // Update buffer size in case it has been limited by AudioFlinger during track creation
     mFrameCount = mCblk->frameCount;
-    mChannelCount = channelCount;
+    mChannelCount = (uint8_t)channelCount;
     mActive = 0;
     mCbf = cbf;
     mNotificationFrames = notificationFrames;
@@ -234,7 +250,11 @@
 
 int AudioRecord::frameSize() const
 {
-    return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+    } else {
+        return sizeof(uint8_t);
+    }
 }
 
 int AudioRecord::inputSource() const
@@ -262,15 +282,18 @@
      }
 
     if (android_atomic_or(1, &mActive) == 0) {
-        mNewPosition = mCblk->user + mUpdatePeriod;
-        mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
-        mCblk->waitTimeMs = 0;
-        if (t != 0) {
-           t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
-        } else {
-            setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+        ret = AudioSystem::startInput(mInput);
+        if (ret == NO_ERROR) {
+            mNewPosition = mCblk->user + mUpdatePeriod;
+            mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+            mCblk->waitTimeMs = 0;
+            if (t != 0) {
+               t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
+            } else {
+                setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+            }
+            ret = mAudioRecord->start();
         }
-        ret = mAudioRecord->start();
     }
 
     if (t != 0) {
@@ -301,6 +324,7 @@
         } else {
             setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
         }
+        AudioSystem::stopInput(mInput);
     }
 
     if (t != 0) {
@@ -421,7 +445,7 @@
         "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
 
     cblk->waitTimeMs = 0;
-    
+
     if (framesReq > framesReady) {
         framesReq = framesReady;
     }
@@ -437,7 +461,7 @@
     audioBuffer->channelCount= mChannelCount;
     audioBuffer->format      = mFormat;
     audioBuffer->frameCount  = framesReq;
-    audioBuffer->size        = framesReq*mChannelCount*sizeof(int16_t);
+    audioBuffer->size        = framesReq*cblk->frameSize;
     audioBuffer->raw         = (int8_t*)cblk->buffer(u);
     active = mActive;
     return active ? status_t(NO_ERROR) : status_t(STOPPED);
@@ -468,7 +492,7 @@
 
     do {
 
-        audioBuffer.frameCount = userSize/mChannelCount/sizeof(int16_t);
+        audioBuffer.frameCount = userSize/frameSize();
 
         // Calling obtainBuffer() with a negative wait count causes
         // an (almost) infinite wait time.
@@ -519,8 +543,8 @@
 
     do {
         audioBuffer.frameCount = frames;
-        // Calling obtainBuffer() with a wait count of 1 
-        // limits wait time to WAIT_PERIOD_MS. This prevents from being 
+        // Calling obtainBuffer() with a wait count of 1
+        // limits wait time to WAIT_PERIOD_MS. This prevents from being
         // stuck here not being able to handle timed events (position, markers).
         status_t err = obtainBuffer(&audioBuffer, 1);
         if (err < NO_ERROR) {
@@ -548,14 +572,14 @@
         if (readSize > reqSize) readSize = reqSize;
 
         audioBuffer.size = readSize;
-        audioBuffer.frameCount = readSize/mChannelCount/sizeof(int16_t);
+        audioBuffer.frameCount = readSize/frameSize();
         frames -= audioBuffer.frameCount;
 
         releaseBuffer(&audioBuffer);
 
     } while (frames);
 
-    
+
     // Manage overrun callback
     if (mActive && (mCblk->framesAvailable_l() == 0)) {
         LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag);
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 86d0542..1fc1024 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -20,8 +20,18 @@
 #include <utils/Log.h>
 #include <binder/IServiceManager.h>
 #include <media/AudioSystem.h>
+#include <media/IAudioPolicyService.h>
 #include <math.h>
 
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+// ----------------------------------------------------------------------------
+
 namespace android {
 
 // client singleton for AudioFlinger binder interface
@@ -30,10 +40,9 @@
 sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
 audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
 // Cached values
-int AudioSystem::gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES];
-int AudioSystem::gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES];
-uint32_t AudioSystem::gOutLatency[NUM_AUDIO_OUTPUT_TYPES];
-bool AudioSystem::gA2dpEnabled;
+DefaultKeyedVector<int, audio_io_handle_t> AudioSystem::gStreamOutputMap(0);
+DefaultKeyedVector<audio_io_handle_t, AudioSystem::OutputDescriptor *> AudioSystem::gOutputs(0);
+
 // Cached values for recording queries
 uint32_t AudioSystem::gPrevInSamplingRate = 16000;
 int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT;
@@ -65,44 +74,12 @@
         binder->linkToDeath(gAudioFlingerClient);
         gAudioFlinger = interface_cast<IAudioFlinger>(binder);
         gAudioFlinger->registerClient(gAudioFlingerClient);
-        // Cache frequently accessed parameters 
-        for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
-            gOutFrameCount[output] = (int)gAudioFlinger->frameCount(output);
-            gOutSamplingRate[output] = (int)gAudioFlinger->sampleRate(output);
-            gOutLatency[output] = gAudioFlinger->latency(output);
-        }
-        gA2dpEnabled = gAudioFlinger->isA2dpEnabled();
     }
     LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
+
     return gAudioFlinger;
 }
 
-// routing helper functions
-status_t AudioSystem::speakerphone(bool state) {
-    uint32_t routes = state ? ROUTE_SPEAKER : ROUTE_EARPIECE;
-    return setRouting(MODE_IN_CALL, routes, ROUTE_ALL);
-}
-
-status_t AudioSystem::isSpeakerphoneOn(bool* state) {
-    uint32_t routes = 0;
-    status_t s = getRouting(MODE_IN_CALL, &routes);
-    *state = !!(routes & ROUTE_SPEAKER);
-    return s;
-}
-
-status_t AudioSystem::bluetoothSco(bool state) {
-    uint32_t mask = ROUTE_BLUETOOTH_SCO;
-    uint32_t routes = state ? mask : ROUTE_EARPIECE;
-    return setRouting(MODE_IN_CALL, routes, ROUTE_ALL);
-}
-
-status_t AudioSystem::isBluetoothScoOn(bool* state) {
-    uint32_t routes = 0;
-    status_t s = getRouting(MODE_IN_CALL, &routes);
-    *state = !!(routes & ROUTE_BLUETOOTH_SCO);
-    return s;
-}
-
 status_t AudioSystem::muteMicrophone(bool state) {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
@@ -148,12 +125,12 @@
     return NO_ERROR;
 }
 
-status_t AudioSystem::setStreamVolume(int stream, float value)
+status_t AudioSystem::setStreamVolume(int stream, float value, void *output)
 {
     if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
-    af->setStreamVolume(stream, value);
+    af->setStreamVolume(stream, value, output);
     return NO_ERROR;
 }
 
@@ -166,12 +143,12 @@
     return NO_ERROR;
 }
 
-status_t AudioSystem::getStreamVolume(int stream, float* volume)
+status_t AudioSystem::getStreamVolume(int stream, float* volume, void *output)
 {
     if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
-    *volume = af->streamVolume(stream);
+    *volume = af->streamVolume(stream, output);
     return NO_ERROR;
 }
 
@@ -192,29 +169,6 @@
     return af->setMode(mode);
 }
 
-status_t AudioSystem::getMode(int* mode)
-{
-    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-    if (af == 0) return PERMISSION_DENIED;
-    *mode = af->getMode();
-    return NO_ERROR;
-}
-
-status_t AudioSystem::setRouting(int mode, uint32_t routes, uint32_t mask)
-{
-    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-    if (af == 0) return PERMISSION_DENIED;
-    return af->setRouting(mode, routes, mask);
-}
-
-status_t AudioSystem::getRouting(int mode, uint32_t* routes)
-{
-    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-    if (af == 0) return PERMISSION_DENIED;
-    uint32_t r = af->getRouting(mode);
-    *routes = r;
-    return NO_ERROR;
-}
 
 status_t AudioSystem::isMusicActive(bool* state) {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
@@ -223,12 +177,20 @@
     return NO_ERROR;
 }
 
-// Temporary interface, do not use
-// TODO: Replace with a more generic key:value get/set mechanism
-status_t AudioSystem::setParameter(const char* key, const char* value) {
+
+status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
-    return af->setParameter(key, value);
+    return af->setParameters(ioHandle, keyValuePairs);
+}
+
+String8 AudioSystem::getParameters(audio_io_handle_t ioHandle, const String8& keys) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    String8 result = String8("");
+    if (af == 0) return result;
+
+    result = af->getParameters(ioHandle, keys);
+    return result;
 }
 
 // convert volume steps to natural log scale
@@ -257,55 +219,108 @@
 
 status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType)
 {
-    int output = getOutput(streamType);
-    
-    if (output == NUM_AUDIO_OUTPUT_TYPES) return PERMISSION_DENIED;
+    OutputDescriptor *outputDesc;
+    audio_io_handle_t output;
 
-    // gOutSamplingRate[] is updated by getOutput() which calls get_audio_flinger()
-    LOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, gOutSamplingRate[output]);
-    
-    *samplingRate = gOutSamplingRate[output];
-    
+    if (streamType == DEFAULT) {
+        streamType = MUSIC;
+    }
+
+    output = getOutput((stream_type)streamType);
+    if (output == 0) {
+        return PERMISSION_DENIED;
+    }
+
+    gLock.lock();
+    outputDesc = AudioSystem::gOutputs.valueFor(output);
+    if (outputDesc == 0) {
+        LOGV("getOutputSamplingRate() no output descriptor for output %p in gOutputs", output);
+        gLock.unlock();
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) return PERMISSION_DENIED;
+        *samplingRate = af->sampleRate(output);
+    } else {
+        LOGV("getOutputSamplingRate() reading from output desc");
+        *samplingRate = outputDesc->samplingRate;
+        gLock.unlock();
+    }
+
+    LOGV("getOutputSamplingRate() streamType %d, output %p, sampling rate %d", streamType, output, *samplingRate);
+
     return NO_ERROR;
 }
 
 status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType)
 {
-    int output = getOutput(streamType);
+    OutputDescriptor *outputDesc;
+    audio_io_handle_t output;
 
-    if (output == NUM_AUDIO_OUTPUT_TYPES) return PERMISSION_DENIED;
+    if (streamType == DEFAULT) {
+        streamType = MUSIC;
+    }
 
-    // gOutFrameCount[] is updated by getOutput() which calls get_audio_flinger()
-    LOGV("getOutputFrameCount() streamType %d, output %d, frame count %d", streamType, output, gOutFrameCount[output]);
+    output = getOutput((stream_type)streamType);
+    if (output == 0) {
+        return PERMISSION_DENIED;
+    }
 
-    *frameCount = gOutFrameCount[output];
-    
+    gLock.lock();
+    outputDesc = AudioSystem::gOutputs.valueFor(output);
+    if (outputDesc == 0) {
+        gLock.unlock();
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) return PERMISSION_DENIED;
+        *frameCount = af->frameCount(output);
+    } else {
+        *frameCount = outputDesc->frameCount;
+        gLock.unlock();
+    }
+
+    LOGV("getOutputFrameCount() streamType %d, output %p, frameCount %d", streamType, output, *frameCount);
+
     return NO_ERROR;
 }
 
 status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType)
 {
-    int output = getOutput(streamType);
+    OutputDescriptor *outputDesc;
+    audio_io_handle_t output;
 
-    if (output == NUM_AUDIO_OUTPUT_TYPES) return PERMISSION_DENIED;
+    if (streamType == DEFAULT) {
+        streamType = MUSIC;
+    }
 
-    // gOutLatency[] is updated by getOutput() which calls get_audio_flinger()
-    LOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, gOutLatency[output]);
+    output = getOutput((stream_type)streamType);
+    if (output == 0) {
+        return PERMISSION_DENIED;
+    }
 
-    *latency = gOutLatency[output];
-    
+    gLock.lock();
+    outputDesc = AudioSystem::gOutputs.valueFor(output);
+    if (outputDesc == 0) {
+        gLock.unlock();
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) return PERMISSION_DENIED;
+        *latency = af->latency(output);
+    } else {
+        *latency = outputDesc->latency;
+        gLock.unlock();
+    }
+
+    LOGV("getOutputLatency() streamType %d, output %p, latency %d", streamType, output, *latency);
+
     return NO_ERROR;
 }
 
-status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount, 
+status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount,
     size_t* buffSize)
 {
     // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values
-    if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat) 
+    if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat)
         || (channelCount != gPrevInChannelCount)) {
         // save the request params
         gPrevInSamplingRate = sampleRate;
-        gPrevInFormat = format; 
+        gPrevInFormat = format;
         gPrevInChannelCount = channelCount;
 
         gInBuffSize = 0;
@@ -314,24 +329,18 @@
             return PERMISSION_DENIED;
         }
         gInBuffSize = af->getInputBufferSize(sampleRate, format, channelCount);
-    } 
+    }
     *buffSize = gInBuffSize;
-    
+
     return NO_ERROR;
 }
 
 // ---------------------------------------------------------------------------
 
-void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {   
+void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
     Mutex::Autolock _l(AudioSystem::gLock);
-    AudioSystem::gAudioFlinger.clear();
 
-    for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
-        gOutFrameCount[output] = 0;
-        gOutSamplingRate[output] = 0;
-        gOutLatency[output] = 0;
-    }
-    AudioSystem::gInBuffSize = 0;
+    AudioSystem::gAudioFlinger.clear();
 
     if (gAudioErrorCallback) {
         gAudioErrorCallback(DEAD_OBJECT);
@@ -339,33 +348,83 @@
     LOGW("AudioFlinger server died!");
 }
 
-void AudioSystem::AudioFlingerClient::a2dpEnabledChanged(bool enabled) {
-    gA2dpEnabled = enabled;        
-    LOGV("AudioFlinger A2DP enabled status changed! %d", enabled);
+void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, void *param1, void *param2) {
+    LOGV("ioConfigChanged() event %d", event);
+    audio_io_handle_t ioHandle = (audio_io_handle_t)param1;
+    OutputDescriptor *desc;
+    uint32_t stream;
+
+    if (param1 == 0) return;
+
+    Mutex::Autolock _l(AudioSystem::gLock);
+
+    switch (event) {
+    case STREAM_CONFIG_CHANGED:
+        if (param2 == 0) break;
+        stream = *(uint32_t *)param2;
+        LOGV("ioConfigChanged() STREAM_CONFIG_CHANGED stream %d, output %p", stream, ioHandle);
+        if (gStreamOutputMap.indexOfKey(stream) >= 0) {
+            gStreamOutputMap.replaceValueFor(stream, ioHandle);
+        }
+        break;
+    case OUTPUT_OPENED: {
+        if (gOutputs.indexOfKey(ioHandle) >= 0) {
+            LOGV("ioConfigChanged() opening already existing output! %p", ioHandle);
+            break;
+        }
+        if (param2 == 0) break;
+        desc = (OutputDescriptor *)param2;
+
+        OutputDescriptor *outputDesc =  new OutputDescriptor(*desc);
+        gOutputs.add(ioHandle, outputDesc);
+        LOGV("ioConfigChanged() new output samplingRate %d, format %d channels %d frameCount %d latency %d",
+                outputDesc->samplingRate, outputDesc->format, outputDesc->channels, outputDesc->frameCount, outputDesc->latency);
+        } break;
+    case OUTPUT_CLOSED: {
+        if (gOutputs.indexOfKey(ioHandle) < 0) {
+            LOGW("ioConfigChanged() closing unknow output! %p", ioHandle);
+            break;
+        }
+        LOGV("ioConfigChanged() output %p closed", ioHandle);
+
+        gOutputs.removeItem(ioHandle);
+        for (int i = gStreamOutputMap.size() - 1; i >= 0 ; i--) {
+            if (gStreamOutputMap.valueAt(i) == ioHandle) {
+                gStreamOutputMap.removeItemsAt(i);
+            }
+        }
+        } break;
+
+    case OUTPUT_CONFIG_CHANGED: {
+        int index = gOutputs.indexOfKey(ioHandle);
+        if (index < 0) {
+            LOGW("ioConfigChanged() modifying unknow output! %p", ioHandle);
+            break;
+        }
+        if (param2 == 0) break;
+        desc = (OutputDescriptor *)param2;
+
+        LOGV("ioConfigChanged() new config for output %p samplingRate %d, format %d channels %d frameCount %d latency %d",
+                ioHandle, desc->samplingRate, desc->format,
+                desc->channels, desc->frameCount, desc->latency);
+        OutputDescriptor *outputDesc = gOutputs.valueAt(index);
+        delete outputDesc;
+        outputDesc =  new OutputDescriptor(*desc);
+        gOutputs.replaceValueFor(ioHandle, outputDesc);
+    } break;
+    case INPUT_OPENED:
+    case INPUT_CLOSED:
+    case INPUT_CONFIG_CHANGED:
+        break;
+
+    }
 }
 
 void AudioSystem::setErrorCallback(audio_error_callback cb) {
-    Mutex::Autolock _l(AudioSystem::gLock);
+    Mutex::Autolock _l(gLock);
     gAudioErrorCallback = cb;
 }
 
-int AudioSystem::getOutput(int streamType)
-{   
-    // make sure that gA2dpEnabled is valid by calling get_audio_flinger() which in turn 
-    // will call gAudioFlinger->isA2dpEnabled()
-    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-    if (af == 0) return NUM_AUDIO_OUTPUT_TYPES;
-
-    if (streamType == DEFAULT) {
-        streamType = MUSIC;
-    }
-    if (gA2dpEnabled && routedToA2dpOutput(streamType)) {
-        return AUDIO_OUTPUT_A2DP;
-    } else {
-        return AUDIO_OUTPUT_HARDWARE;
-    }
-}
-
 bool AudioSystem::routedToA2dpOutput(int streamType) {
     switch(streamType) {
     case MUSIC:
@@ -379,6 +438,451 @@
 }
 
 
+// client singleton for AudioPolicyService binder interface
+sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
+sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient;
+
+
+// establish binder interface to AudioFlinger service
+const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service()
+{
+    gLock.lock();
+    if (gAudioPolicyService.get() == 0) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder;
+        do {
+            binder = sm->getService(String16("media.audio_policy"));
+            if (binder != 0)
+                break;
+            LOGW("AudioPolicyService not published, waiting...");
+            usleep(500000); // 0.5 s
+        } while(true);
+        if (gAudioPolicyServiceClient == NULL) {
+            gAudioPolicyServiceClient = new AudioPolicyServiceClient();
+        }
+        binder->linkToDeath(gAudioPolicyServiceClient);
+        gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
+        gLock.unlock();
+    } else {
+        gLock.unlock();
+    }
+    return gAudioPolicyService;
+}
+
+status_t AudioSystem::setDeviceConnectionState(audio_devices device,
+                                                  device_connection_state state,
+                                                  const char *device_address)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+
+    return aps->setDeviceConnectionState(device, state, device_address);
+}
+
+AudioSystem::device_connection_state AudioSystem::getDeviceConnectionState(audio_devices device,
+                                                  const char *device_address)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return DEVICE_STATE_UNAVAILABLE;
+
+    return aps->getDeviceConnectionState(device, device_address);
+}
+
+status_t AudioSystem::setPhoneState(int state)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+
+    return aps->setPhoneState(state);
+}
+
+status_t AudioSystem::setRingerMode(uint32_t mode, uint32_t mask)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->setRingerMode(mode, mask);
+}
+
+status_t AudioSystem::setForceUse(force_use usage, forced_config config)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->setForceUse(usage, config);
+}
+
+AudioSystem::forced_config AudioSystem::getForceUse(force_use usage)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return FORCE_NONE;
+    return aps->getForceUse(usage);
+}
+
+
+audio_io_handle_t AudioSystem::getOutput(stream_type stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    output_flags flags)
+{
+    audio_io_handle_t output = NULL;
+    if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) {
+        Mutex::Autolock _l(gLock);
+        output = AudioSystem::gStreamOutputMap.valueFor(stream);
+        LOGV_IF((output != NULL), "getOutput() read %p from cache for stream %d", output, stream);
+    }
+    if (output == NULL) {
+        const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+        if (aps == 0) return NULL;
+        output = aps->getOutput(stream, samplingRate, format, channels, flags);
+        if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) {
+            Mutex::Autolock _l(gLock);
+            AudioSystem::gStreamOutputMap.add(stream, output);
+        }
+    }
+    return output;
+}
+
+status_t AudioSystem::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->startOutput(output, stream);
+}
+
+status_t AudioSystem::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->stopOutput(output, stream);
+}
+
+void AudioSystem::releaseOutput(audio_io_handle_t output)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return;
+    aps->releaseOutput(output);
+}
+
+audio_io_handle_t AudioSystem::getInput(int inputSource,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    audio_in_acoustics acoustics)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return NULL;
+    return aps->getInput(inputSource, samplingRate, format, channels, acoustics);
+}
+
+status_t AudioSystem::startInput(audio_io_handle_t input)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->startInput(input);
+}
+
+status_t AudioSystem::stopInput(audio_io_handle_t input)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->stopInput(input);
+}
+
+void AudioSystem::releaseInput(audio_io_handle_t input)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return;
+    aps->releaseInput(input);
+}
+
+status_t AudioSystem::initStreamVolume(stream_type stream,
+                                    int indexMin,
+                                    int indexMax)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->initStreamVolume(stream, indexMin, indexMax);
+}
+
+status_t AudioSystem::setStreamVolumeIndex(stream_type stream, int index)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->setStreamVolumeIndex(stream, index);
+}
+
+status_t AudioSystem::getStreamVolumeIndex(stream_type stream, int *index)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->getStreamVolumeIndex(stream, index);
+}
+
+// ---------------------------------------------------------------------------
+
+void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) {
+    Mutex::Autolock _l(AudioSystem::gLock);
+    AudioSystem::gAudioPolicyService.clear();
+
+    LOGW("AudioPolicyService server died!");
+}
+
+// ---------------------------------------------------------------------------
+
+
+// use emulated popcount optimization
+// http://www.df.lth.se/~john_e/gems/gem002d.html
+uint32_t AudioSystem::popCount(uint32_t u)
+{
+    u = ((u&0x55555555) + ((u>>1)&0x55555555));
+    u = ((u&0x33333333) + ((u>>2)&0x33333333));
+    u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
+    u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
+    u = ( u&0x0000ffff) + (u>>16);
+    return u;
+}
+
+bool AudioSystem::isOutputDevice(audio_devices device)
+{
+    if ((popCount(device) == 1 ) &&
+        ((device & ~AudioSystem::DEVICE_OUT_ALL) == 0)) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isInputDevice(audio_devices device)
+{
+    if ((popCount(device) == 1 ) &&
+        ((device & ~AudioSystem::DEVICE_IN_ALL) == 0)) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isA2dpDevice(audio_devices device)
+{
+    if ((popCount(device) == 1 ) &&
+        (device & (AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP |
+                   AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+                   AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER))) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isBluetoothScoDevice(audio_devices device)
+{
+    if ((popCount(device) == 1 ) &&
+        (device & (AudioSystem::DEVICE_OUT_BLUETOOTH_SCO |
+                   AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
+                   AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT))) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isLowVisibility(stream_type stream)
+{
+    if (stream == AudioSystem::SYSTEM || stream == AudioSystem::NOTIFICATION) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isInputChannel(uint32_t channel)
+{
+    if ((channel & ~AudioSystem::CHANNEL_IN_ALL) == 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isOutputChannel(uint32_t channel)
+{
+    if ((channel & ~AudioSystem::CHANNEL_OUT_ALL) == 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isValidFormat(uint32_t format)
+{
+    switch (format & MAIN_FORMAT_MASK) {
+    case         PCM:
+    case         MP3:
+    case         AMR_NB:
+    case         AMR_WB:
+    case         AAC:
+    case         HE_AAC_V1:
+    case         HE_AAC_V2:
+    case         VORBIS:
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool AudioSystem::isLinearPCM(uint32_t format)
+{
+    switch (format) {
+    case         PCM_16_BIT:
+    case         PCM_8_BIT:
+        return true;
+    default:
+        return false;
+    }
+}
+
+//------------------------- AudioParameter class implementation ---------------
+
+const char *AudioParameter::keyRouting = "routing";
+const char *AudioParameter::keySamplingRate = "sampling_rate";
+const char *AudioParameter::keyFormat = "format";
+const char *AudioParameter::keyChannels = "channels";
+const char *AudioParameter::keyFrameCount = "frame_count";
+
+AudioParameter::AudioParameter(const String8& keyValuePairs)
+{
+    char *str = new char[keyValuePairs.length()+1];
+    mKeyValuePairs = keyValuePairs;
+
+    strcpy(str, keyValuePairs.string());
+    char *pair = strtok(str, ";");
+    while (pair != NULL) {
+        if (strlen(pair) != 0) {
+            size_t eqIdx = strcspn(pair, "=");
+            String8 key = String8(pair, eqIdx);
+            String8 value;
+            if (eqIdx == strlen(pair)) {
+                value = String8("");
+            } else {
+                value = String8(pair + eqIdx + 1);
+            }
+            if (mParameters.indexOfKey(key) < 0) {
+                mParameters.add(key, value);
+            } else {
+                mParameters.replaceValueFor(key, value);
+            }
+        } else {
+            LOGV("AudioParameter() cstor empty key value pair");
+        }
+        pair = strtok(NULL, ";");
+    }
+
+    delete[] str;
+}
+
+AudioParameter::~AudioParameter()
+{
+    mParameters.clear();
+}
+
+String8 AudioParameter::toString()
+{
+    String8 str = String8("");
+
+    size_t size = mParameters.size();
+    for (size_t i = 0; i < size; i++) {
+        str += mParameters.keyAt(i);
+        str += "=";
+        str += mParameters.valueAt(i);
+        if (i < (size - 1)) str += ";";
+    }
+    return str;
+}
+
+status_t AudioParameter::add(const String8& key, const String8& value)
+{
+    if (mParameters.indexOfKey(key) < 0) {
+        mParameters.add(key, value);
+        return NO_ERROR;
+    } else {
+        mParameters.replaceValueFor(key, value);
+        return ALREADY_EXISTS;
+    }
+}
+
+status_t AudioParameter::addInt(const String8& key, const int value)
+{
+    char str[12];
+    if (snprintf(str, 12, "%d", value) > 0) {
+        String8 str8 = String8(str);
+        return add(key, str8);
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::addFloat(const String8& key, const float value)
+{
+    char str[23];
+    if (snprintf(str, 23, "%.10f", value) > 0) {
+        String8 str8 = String8(str);
+        return add(key, str8);
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::remove(const String8& key)
+{
+    if (mParameters.indexOfKey(key) >= 0) {
+        mParameters.removeItem(key);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::get(const String8& key, String8& value)
+{
+    if (mParameters.indexOfKey(key) >= 0) {
+        value = mParameters.valueFor(key);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::getInt(const String8& key, int& value)
+{
+    String8 str8;
+    status_t result = get(key, str8);
+    value = 0;
+    if (result == NO_ERROR) {
+        int val;
+        if (sscanf(str8.string(), "%d", &val) == 1) {
+            value = val;
+        } else {
+            result = INVALID_OPERATION;
+        }
+    }
+    return result;
+}
+
+status_t AudioParameter::getFloat(const String8& key, float& value)
+{
+    String8 str8;
+    status_t result = get(key, str8);
+    value = 0;
+    if (result == NO_ERROR) {
+        float val;
+        if (sscanf(str8.string(), "%f", &val) == 1) {
+            value = val;
+        } else {
+            result = INVALID_OPERATION;
+        }
+    }
+    return result;
+}
 
 }; // namespace android
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7b9eda7..b147d25 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -54,7 +54,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        int channels,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -62,7 +62,7 @@
         int notificationFrames)
     : mStatus(NO_INIT)
 {
-    mStatus = set(streamType, sampleRate, format, channelCount,
+    mStatus = set(streamType, sampleRate, format, channels,
             frameCount, flags, cbf, user, notificationFrames, 0);
 }
 
@@ -70,7 +70,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        int channels,
         const sp<IMemory>& sharedBuffer,
         uint32_t flags,
         callback_t cbf,
@@ -78,7 +78,7 @@
         int notificationFrames)
     : mStatus(NO_INIT)
 {
-    mStatus = set(streamType, sampleRate, format, channelCount,
+    mStatus = set(streamType, sampleRate, format, channels,
             0, flags, cbf, user, notificationFrames, sharedBuffer);
 }
 
@@ -97,6 +97,7 @@
         }
         mAudioTrack.clear();
         IPCThreadState::self()->flushCommands();
+        AudioSystem::releaseOutput(getOutput());
     }
 }
 
@@ -104,7 +105,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        int channels,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -150,63 +151,84 @@
     if (format == 0) {
         format = AudioSystem::PCM_16_BIT;
     }
-    if (channelCount == 0) {
-        channelCount = 2;
+    if (channels == 0) {
+        channels = AudioSystem::CHANNEL_OUT_STEREO;
     }
 
     // validate parameters
-    if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) &&
-        (format != AudioSystem::PCM_16_BIT)) {
+    if (!AudioSystem::isValidFormat(format)) {
         LOGE("Invalid format");
         return BAD_VALUE;
     }
-    if (channelCount != 1 && channelCount != 2) {
-        LOGE("Invalid channel number");
+
+    // force direct flag if format is not linear PCM
+    if (!AudioSystem::isLinearPCM(format)) {
+        flags |= AudioSystem::OUTPUT_FLAG_DIRECT;
+    }
+
+    if (!AudioSystem::isOutputChannel(channels)) {
+        LOGE("Invalid channel mask");
+        return BAD_VALUE;
+    }
+    uint32_t channelCount = AudioSystem::popCount(channels);
+
+    audio_io_handle_t output = AudioSystem::getOutput((AudioSystem::stream_type)streamType,
+            sampleRate, format, channels, (AudioSystem::output_flags)flags);
+
+    if (output == 0) {
+        LOGE("Could not get audio output for stream type %d", streamType);
         return BAD_VALUE;
     }
 
-    // Ensure that buffer depth covers at least audio hardware latency
-    uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
-    if (minBufCount < 2) minBufCount = 2;
-
-    // When playing from shared buffer, playback will start even if last audioflinger
-    // block is partly filled.
-    if (sharedBuffer != 0 && minBufCount > 1) {
-        minBufCount--;
-    }
-
-    int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
-
-    if (sharedBuffer == 0) {
-        if (frameCount == 0) {
-            frameCount = minFrameCount;
-        }
-        if (notificationFrames == 0) {
-            notificationFrames = frameCount/2;
-        }
-        // Make sure that application is notified with sufficient margin
-        // before underrun
-        if (notificationFrames > frameCount/2) {
-            notificationFrames = frameCount/2;
+    if (!AudioSystem::isLinearPCM(format)) {
+        if (sharedBuffer != 0) {
+            frameCount = sharedBuffer->size();
         }
     } else {
-        // Ensure that buffer alignment matches channelcount
-        if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
-            LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
-            return BAD_VALUE;
-        }
-        frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
-    }
+        // Ensure that buffer depth covers at least audio hardware latency
+        uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
+        if (minBufCount < 2) minBufCount = 2;
 
-    if (frameCount < minFrameCount) {
-      LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
-      return BAD_VALUE;
+        int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
+
+        if (sharedBuffer == 0) {
+            if (frameCount == 0) {
+                frameCount = minFrameCount;
+            }
+            if (notificationFrames == 0) {
+                notificationFrames = frameCount/2;
+            }
+            // Make sure that application is notified with sufficient margin
+            // before underrun
+            if (notificationFrames > frameCount/2) {
+                notificationFrames = frameCount/2;
+            }
+            if (frameCount < minFrameCount) {
+              LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
+              return BAD_VALUE;
+            }
+        } else {
+            // Ensure that buffer alignment matches channelcount
+            if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
+                LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
+                return BAD_VALUE;
+            }
+            frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
+        }
     }
 
     // create the track
     status_t status;
     sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
-                streamType, sampleRate, format, channelCount, frameCount, flags, sharedBuffer, &status);
+                                                      streamType,
+                                                      sampleRate,
+                                                      format,
+                                                      channelCount,
+                                                      frameCount,
+                                                      ((uint16_t)flags) << 16,
+                                                      sharedBuffer,
+                                                      output,
+                                                      &status);
 
     if (track == 0) {
         LOGE("AudioFlinger could not create track, status: %d", status);
@@ -245,6 +267,7 @@
     mVolume[RIGHT] = 1.0f;
     mStreamType = streamType;
     mFormat = format;
+    mChannels = channels;
     mChannelCount = channelCount;
     mSharedBuffer = sharedBuffer;
     mMuted = false;
@@ -259,6 +282,7 @@
     mMarkerReached = false;
     mNewPosition = 0;
     mUpdatePeriod = 0;
+    mFlags = flags;
 
     return NO_ERROR;
 }
@@ -297,7 +321,11 @@
 
 int AudioTrack::frameSize() const
 {
-    return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+    } else {
+        return sizeof(uint8_t);
+    }
 }
 
 sp<IMemory>& AudioTrack::sharedBuffer()
@@ -323,6 +351,7 @@
      }
 
     if (android_atomic_or(1, &mActive) == 0) {
+        AudioSystem::startOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
         mNewPosition = mCblk->server + mUpdatePeriod;
         mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
         mCblk->waitTimeMs = 0;
@@ -367,6 +396,7 @@
         } else {
             setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
         }
+        AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
     }
 
     if (t != 0) {
@@ -382,12 +412,12 @@
 void AudioTrack::flush()
 {
     LOGV("flush");
-    
+
     // clear playback marker and periodic update counter
     mMarkerPosition = 0;
     mMarkerReached = false;
     mUpdatePeriod = 0;
-    
+
 
     if (!mActive) {
         mAudioTrack->flush();
@@ -403,6 +433,7 @@
     if (android_atomic_and(~1, &mActive) == 1) {
         mActive = 0;
         mAudioTrack->pause();
+        AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
     }
 }
 
@@ -455,7 +486,6 @@
 {
     audio_track_cblk_t* cblk = mCblk;
 
-
     Mutex::Autolock _l(cblk->lock);
 
     if (loopCount == 0) {
@@ -476,7 +506,7 @@
         LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
             loopStart, loopEnd, mFrameCount);
         return BAD_VALUE;
-    }   
+    }
 
     cblk->loopStart = loopStart;
     cblk->loopEnd = loopEnd;
@@ -555,7 +585,7 @@
 
     mCblk->server = position;
     mCblk->forceReady = 1;
-    
+
     return NO_ERROR;
 }
 
@@ -571,7 +601,7 @@
 status_t AudioTrack::reload()
 {
     if (!stopped()) return INVALID_OPERATION;
-    
+
     flush();
 
     mCblk->stepUser(mFrameCount);
@@ -579,6 +609,12 @@
     return NO_ERROR;
 }
 
+audio_io_handle_t AudioTrack::getOutput()
+{
+    return AudioSystem::getOutput((AudioSystem::stream_type)mStreamType,
+            mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags);
+}
+
 // -------------------------------------------------------------------------
 
 status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
@@ -608,7 +644,7 @@
                 return WOULD_BLOCK;
             timeout = 0;
             result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
-            if (__builtin_expect(result!=NO_ERROR, false)) { 
+            if (__builtin_expect(result!=NO_ERROR, false)) {
                 cblk->waitTimeMs += waitTimeMs;
                 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
                     // timing out when a loop has been set and we have already written upto loop end
@@ -616,7 +652,7 @@
                     if (cblk->user < cblk->loopEnd) {
                         LOGW(   "obtainBuffer timed out (is the CPU pegged?) %p "
                                 "user=%08x, server=%08x", this, cblk->user, cblk->server);
-                        //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140) 
+                        //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
                         cblk->lock.unlock();
                         mAudioTrack->start();
                         cblk->lock.lock();
@@ -624,7 +660,7 @@
                     }
                     cblk->waitTimeMs = 0;
                 }
-                
+
                 if (--waitCount == 0) {
                     return TIMED_OUT;
                 }
@@ -636,7 +672,7 @@
     }
 
     cblk->waitTimeMs = 0;
-    
+
     if (framesReq > framesAvail) {
         framesReq = framesAvail;
     }
@@ -653,12 +689,16 @@
         "but didn't need to be locked. We recovered, but "
         "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
 
-    audioBuffer->flags       = mMuted ? Buffer::MUTE : 0;
-    audioBuffer->channelCount= mChannelCount;
-    audioBuffer->format      = AudioSystem::PCM_16_BIT;
-    audioBuffer->frameCount  = framesReq;
-    audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t);
-    audioBuffer->raw         = (int8_t *)cblk->buffer(u);
+    audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
+    audioBuffer->channelCount = mChannelCount;
+    audioBuffer->frameCount = framesReq;
+    audioBuffer->size = framesReq * cblk->frameSize;
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        audioBuffer->format = AudioSystem::PCM_16_BIT;
+    } else {
+        audioBuffer->format = mFormat;
+    }
+    audioBuffer->raw = (int8_t *)cblk->buffer(u);
     active = mActive;
     return active ? status_t(NO_ERROR) : status_t(STOPPED);
 }
@@ -690,10 +730,8 @@
     Buffer audioBuffer;
 
     do {
-        audioBuffer.frameCount = userSize/mChannelCount;
-        if (mFormat == AudioSystem::PCM_16_BIT) {
-            audioBuffer.frameCount >>= 1;
-        }
+        audioBuffer.frameCount = userSize/frameSize();
+
         // Calling obtainBuffer() with a negative wait count causes
         // an (almost) infinite wait time.
         status_t err = obtainBuffer(&audioBuffer, -1);
@@ -705,6 +743,7 @@
         }
 
         size_t toWrite;
+
         if (mFormat == AudioSystem::PCM_8_BIT) {
             // Divide capacity by 2 to take expansion into account
             toWrite = audioBuffer.size>>1;
@@ -742,13 +781,13 @@
         if (mCblk->flowControlFlag == 0) {
             mCbf(EVENT_UNDERRUN, mUserData, 0);
             if (mCblk->server == mCblk->frameCount) {
-                mCbf(EVENT_BUFFER_END, mUserData, 0);                
+                mCbf(EVENT_BUFFER_END, mUserData, 0);
             }
             mCblk->flowControlFlag = 1;
             if (mSharedBuffer != 0) return false;
         }
     }
-    
+
     // Manage loop end callback
     while (mLoopCount > mCblk->loopCount) {
         int loopCount = -1;
@@ -767,7 +806,7 @@
     }
 
     // Manage new position callback
-    if(mUpdatePeriod > 0) {
+    if (mUpdatePeriod > 0) {
         while (mCblk->server >= mNewPosition) {
             mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
             mNewPosition += mUpdatePeriod;
@@ -784,10 +823,10 @@
     do {
 
         audioBuffer.frameCount = frames;
-        
-        // Calling obtainBuffer() with a wait count of 1 
-        // limits wait time to WAIT_PERIOD_MS. This prevents from being 
-        // stuck here not being able to handle timed events (position, markers, loops). 
+
+        // Calling obtainBuffer() with a wait count of 1
+        // limits wait time to WAIT_PERIOD_MS. This prevents from being
+        // stuck here not being able to handle timed events (position, markers, loops).
         status_t err = obtainBuffer(&audioBuffer, 1);
         if (err < NO_ERROR) {
             if (err != TIMED_OUT) {
@@ -832,7 +871,11 @@
         }
 
         audioBuffer.size = writtenSize;
-        audioBuffer.frameCount = writtenSize/mChannelCount/sizeof(int16_t);
+        // NOTE: mCblk->frameSize is not equal to AudioTrack::frameSize() for
+        // 8 bit PCM data: in this case,  mCblk->frameSize is based on a sampel size of
+        // 16 bit.
+        audioBuffer.frameCount = writtenSize/mCblk->frameSize;
+
         frames -= audioBuffer.frameCount;
 
         releaseBuffer(&audioBuffer);
@@ -949,7 +992,7 @@
         // we switch to normal obtainBuffer() timeout period
         if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
             bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
-        }        
+        }
         // It is possible that we receive a flush()
         // while the mixer is processing a block: in this case,
         // stepServer() is called After the flush() has reset u & s and
@@ -981,7 +1024,7 @@
 
 void* audio_track_cblk_t::buffer(uint32_t offset) const
 {
-    return (int16_t *)this->buffers + (offset-userBase)*this->channels;
+    return (int8_t *)this->buffers + (offset - userBase) * this->frameSize;
 }
 
 uint32_t audio_track_cblk_t::framesAvailable()
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 6fc0cb7..9385367 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -16,6 +16,7 @@
 */
 
 #define LOG_TAG "IAudioFlinger"
+//#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
 #include <stdint.h>
@@ -44,17 +45,21 @@
     STREAM_VOLUME,
     STREAM_MUTE,
     SET_MODE,
-    GET_MODE,
-    SET_ROUTING,
-    GET_ROUTING,
     SET_MIC_MUTE,
     GET_MIC_MUTE,
     IS_MUSIC_ACTIVE,
-    SET_PARAMETER,
+    SET_PARAMETERS,
+    GET_PARAMETERS,
     REGISTER_CLIENT,
     GET_INPUTBUFFERSIZE,
-    WAKE_UP,
-    IS_A2DP_ENABLED
+    OPEN_OUTPUT,
+    OPEN_DUPLICATE_OUTPUT,
+    CLOSE_OUTPUT,
+    SUSPEND_OUTPUT,
+    RESTORE_OUTPUT,
+    OPEN_INPUT,
+    CLOSE_INPUT,
+    SET_STREAM_OUTPUT
 };
 
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -74,6 +79,7 @@
                                 int frameCount,
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
+                                void *output,
                                 status_t *status)
     {
         Parcel data, reply;
@@ -86,6 +92,7 @@
         data.writeInt32(frameCount);
         data.writeInt32(flags);
         data.writeStrongBinder(sharedBuffer->asBinder());
+        data.write(&output, sizeof(void *));
         status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
         if (lStatus != NO_ERROR) {
             LOGE("createTrack error: %s", strerror(-lStatus));
@@ -99,7 +106,7 @@
 
     virtual sp<IAudioRecord> openRecord(
                                 pid_t pid,
-                                int inputSource,
+                                void *input,
                                 uint32_t sampleRate,
                                 int format,
                                 int channelCount,
@@ -110,7 +117,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.writeInt32(pid);
-        data.writeInt32(inputSource);
+        data.write(&input, sizeof(void *));
         data.writeInt32(sampleRate);
         data.writeInt32(format);
         data.writeInt32(channelCount);
@@ -124,47 +131,47 @@
         return interface_cast<IAudioRecord>(reply.readStrongBinder());
     }
 
-    virtual uint32_t sampleRate(int output) const
+    virtual uint32_t sampleRate(void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(output);
+        data.write(&output, sizeof(void *));
         remote()->transact(SAMPLE_RATE, data, &reply);
         return reply.readInt32();
     }
 
-    virtual int channelCount(int output) const
+    virtual int channelCount(void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(output);
+        data.write(&output, sizeof(void *));
         remote()->transact(CHANNEL_COUNT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual int format(int output) const
+    virtual int format(void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(output);
+        data.write(&output, sizeof(void *));
         remote()->transact(FORMAT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual size_t frameCount(int output) const
+    virtual size_t frameCount(void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(output);
+        data.write(&output, sizeof(void *));
         remote()->transact(FRAME_COUNT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual uint32_t latency(int output) const
+    virtual uint32_t latency(void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(output);
+        data.write(&output, sizeof(void *));
         remote()->transact(LATENCY, data, &reply);
         return reply.readInt32();
     }
@@ -203,12 +210,13 @@
         return reply.readInt32();
     }
 
-    virtual status_t setStreamVolume(int stream, float value)
+    virtual status_t setStreamVolume(int stream, float value, void *output)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.writeInt32(stream);
         data.writeFloat(value);
+        data.write(&output, sizeof(void *));
         remote()->transact(SET_STREAM_VOLUME, data, &reply);
         return reply.readInt32();
     }
@@ -223,11 +231,12 @@
         return reply.readInt32();
     }
 
-    virtual float streamVolume(int stream) const
+    virtual float streamVolume(int stream, void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.writeInt32(stream);
+        data.write(&output, sizeof(void *));
         remote()->transact(STREAM_VOLUME, data, &reply);
         return reply.readFloat();
     }
@@ -241,26 +250,6 @@
         return reply.readInt32();
     }
 
-    virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(mode);
-        data.writeInt32(routes);
-        data.writeInt32(mask);
-        remote()->transact(SET_ROUTING, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual uint32_t getRouting(int mode) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(mode);
-        remote()->transact(GET_ROUTING, data, &reply);
-        return reply.readInt32();
-    }
-
     virtual status_t setMode(int mode)
     {
         Parcel data, reply;
@@ -270,14 +259,6 @@
         return reply.readInt32();
     }
 
-    virtual int getMode() const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(GET_MODE, data, &reply);
-        return reply.readInt32();
-    }
-
     virtual status_t setMicMute(bool state)
     {
         Parcel data, reply;
@@ -303,16 +284,26 @@
         return reply.readInt32();
     }
 
-    virtual status_t setParameter(const char* key, const char* value)
+    virtual status_t setParameters(void *ioHandle, const String8& keyValuePairs)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeCString(key);
-        data.writeCString(value);
-        remote()->transact(SET_PARAMETER, data, &reply);
+        data.write(&ioHandle, sizeof(void *));
+        data.writeString8(keyValuePairs);
+        remote()->transact(SET_PARAMETERS, data, &reply);
         return reply.readInt32();
     }
-    
+
+    virtual String8 getParameters(void *ioHandle, const String8& keys)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(&ioHandle, sizeof(void *));
+        data.writeString8(keys);
+        remote()->transact(GET_PARAMETERS, data, &reply);
+        return reply.readString8();
+    }
+
     virtual void registerClient(const sp<IAudioFlingerClient>& client)
     {
         Parcel data, reply;
@@ -320,7 +311,7 @@
         data.writeStrongBinder(client->asBinder());
         remote()->transact(REGISTER_CLIENT, data, &reply);
     }
-    
+
     virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
     {
         Parcel data, reply;
@@ -331,21 +322,133 @@
         remote()->transact(GET_INPUTBUFFERSIZE, data, &reply);
         return reply.readInt32();
     }
-    
-    virtual void wakeUp()
+
+    virtual void *openOutput(uint32_t *pDevices,
+                            uint32_t *pSamplingRate,
+                            uint32_t *pFormat,
+                            uint32_t *pChannels,
+                            uint32_t *pLatencyMs,
+                            uint32_t flags)
     {
         Parcel data, reply;
+        uint32_t devices = pDevices ? *pDevices : 0;
+        uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+        uint32_t format = pFormat ? *pFormat : 0;
+        uint32_t channels = pChannels ? *pChannels : 0;
+        uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
+
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(WAKE_UP, data, &reply, IBinder::FLAG_ONEWAY);
-        return;
+        data.writeInt32(devices);
+        data.writeInt32(samplingRate);
+        data.writeInt32(format);
+        data.writeInt32(channels);
+        data.writeInt32(latency);
+        data.writeInt32(flags);
+        remote()->transact(OPEN_OUTPUT, data, &reply);
+        void *output;
+        reply.read(&output, sizeof(void *));
+        LOGV("openOutput() returned output, %p", output);
+        devices = reply.readInt32();
+        if (pDevices) *pDevices = devices;
+        samplingRate = reply.readInt32();
+        if (pSamplingRate) *pSamplingRate = samplingRate;
+        format = reply.readInt32();
+        if (pFormat) *pFormat = format;
+        channels = reply.readInt32();
+        if (pChannels) *pChannels = channels;
+        latency = reply.readInt32();
+        if (pLatencyMs) *pLatencyMs = latency;
+        return output;
     }
 
-    virtual bool isA2dpEnabled() const
+    virtual void *openDuplicateOutput(void *output1, void *output2)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(IS_A2DP_ENABLED, data, &reply);
-        return (bool)reply.readInt32();
+        data.write(&output1, sizeof(void *));
+        data.write(&output2, sizeof(void *));
+        remote()->transact(OPEN_DUPLICATE_OUTPUT, data, &reply);
+        void *output;
+        reply.read(&output, sizeof(void *));
+        return output;
+    }
+
+    virtual status_t closeOutput(void *output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(&output, sizeof(void *));
+        remote()->transact(CLOSE_OUTPUT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t suspendOutput(void *output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(&output, sizeof(void *));
+        remote()->transact(SUSPEND_OUTPUT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t restoreOutput(void *output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(&output, sizeof(void *));
+        remote()->transact(RESTORE_OUTPUT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual void *openInput(uint32_t *pDevices,
+                                        uint32_t *pSamplingRate,
+                                        uint32_t *pFormat,
+                                        uint32_t *pChannels,
+                                        uint32_t acoustics)
+    {
+        Parcel data, reply;
+        uint32_t devices = pDevices ? *pDevices : 0;
+        uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+        uint32_t format = pFormat ? *pFormat : 0;
+        uint32_t channels = pChannels ? *pChannels : 0;
+
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(devices);
+        data.writeInt32(samplingRate);
+        data.writeInt32(format);
+        data.writeInt32(channels);
+        data.writeInt32(acoustics);
+        remote()->transact(OPEN_INPUT, data, &reply);
+        void *input;
+        reply.read(&input, sizeof(void *));
+        devices = reply.readInt32();
+        if (pDevices) *pDevices = devices;
+        samplingRate = reply.readInt32();
+        if (pSamplingRate) *pSamplingRate = samplingRate;
+        format = reply.readInt32();
+        if (pFormat) *pFormat = format;
+        channels = reply.readInt32();
+        if (pChannels) *pChannels = channels;
+        return input;
+    }
+
+    virtual status_t closeInput(void *input)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(&input, sizeof(void *));
+        remote()->transact(CLOSE_INPUT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setStreamOutput(uint32_t stream, void *output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(stream);
+        data.write(&output, sizeof(void *));
+        remote()->transact(SET_STREAM_OUTPUT, data, &reply);
+        return reply.readInt32();
     }
 };
 
@@ -367,10 +470,12 @@
             size_t bufferCount = data.readInt32();
             uint32_t flags = data.readInt32();
             sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder());
+            void *output;
+            data.read(&output, sizeof(void *));
             status_t status;
             sp<IAudioTrack> track = createTrack(pid,
                     streamType, sampleRate, format,
-                    channelCount, bufferCount, flags, buffer, &status);
+                    channelCount, bufferCount, flags, buffer, output, &status);
             reply->writeInt32(status);
             reply->writeStrongBinder(track->asBinder());
             return NO_ERROR;
@@ -378,14 +483,15 @@
         case OPEN_RECORD: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             pid_t pid = data.readInt32();
-            int inputSource = data.readInt32();
+            void *input;
+            data.read(&input, sizeof(void *));
             uint32_t sampleRate = data.readInt32();
             int format = data.readInt32();
             int channelCount = data.readInt32();
             size_t bufferCount = data.readInt32();
             uint32_t flags = data.readInt32();
             status_t status;
-            sp<IAudioRecord> record = openRecord(pid, inputSource,
+            sp<IAudioRecord> record = openRecord(pid, input,
                     sampleRate, format, channelCount, bufferCount, flags, &status);
             reply->writeInt32(status);
             reply->writeStrongBinder(record->asBinder());
@@ -393,31 +499,36 @@
         } break;
         case SAMPLE_RATE: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int output = data.readInt32();
+            void *output;
+            data.read(&output, sizeof(void *));
             reply->writeInt32( sampleRate(output) );
             return NO_ERROR;
         } break;
         case CHANNEL_COUNT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int output = data.readInt32();
+            void *output;
+            data.read(&output, sizeof(void *));
             reply->writeInt32( channelCount(output) );
             return NO_ERROR;
         } break;
         case FORMAT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int output = data.readInt32();
+            void *output;
+            data.read(&output, sizeof(void *));
             reply->writeInt32( format(output) );
             return NO_ERROR;
         } break;
         case FRAME_COUNT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int output = data.readInt32();
+            void *output;
+            data.read(&output, sizeof(void *));
             reply->writeInt32( frameCount(output) );
             return NO_ERROR;
         } break;
         case LATENCY: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int output = data.readInt32();
+            void *output;
+            data.read(&output, sizeof(void *));
             reply->writeInt32( latency(output) );
             return NO_ERROR;
         } break;
@@ -444,7 +555,10 @@
         case SET_STREAM_VOLUME: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             int stream = data.readInt32();
-            reply->writeInt32( setStreamVolume(stream, data.readFloat()) );
+            float volume = data.readFloat();
+            void *output;
+            data.read(&output, sizeof(void *));
+            reply->writeInt32( setStreamVolume(stream, volume, output) );
             return NO_ERROR;
         } break;
         case SET_STREAM_MUTE: {
@@ -456,7 +570,9 @@
         case STREAM_VOLUME: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             int stream = data.readInt32();
-            reply->writeFloat( streamVolume(stream) );
+            void *output;
+            data.read(&output, sizeof(void *));
+            reply->writeFloat( streamVolume(stream, output) );
             return NO_ERROR;
         } break;
         case STREAM_MUTE: {
@@ -465,31 +581,12 @@
             reply->writeInt32( streamMute(stream) );
             return NO_ERROR;
         } break;
-        case SET_ROUTING: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int mode = data.readInt32();
-            uint32_t routes = data.readInt32();
-            uint32_t mask = data.readInt32();
-            reply->writeInt32( setRouting(mode, routes, mask) );
-            return NO_ERROR;
-        } break;
-        case GET_ROUTING: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int mode = data.readInt32();
-            reply->writeInt32( getRouting(mode) );
-            return NO_ERROR;
-        } break;
         case SET_MODE: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             int mode = data.readInt32();
             reply->writeInt32( setMode(mode) );
             return NO_ERROR;
         } break;
-        case GET_MODE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( getMode() );
-            return NO_ERROR;
-        } break;
         case SET_MIC_MUTE: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             int state = data.readInt32();
@@ -506,13 +603,23 @@
             reply->writeInt32( isMusicActive() );
             return NO_ERROR;
         } break;
-        case SET_PARAMETER: {
+        case SET_PARAMETERS: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            const char *key = data.readCString();
-            const char *value = data.readCString();
-            reply->writeInt32( setParameter(key, value) );
+            void *ioHandle;
+            data.read(&ioHandle, sizeof(void *));
+            String8 keyValuePairs(data.readString8());
+            reply->writeInt32(setParameters(ioHandle, keyValuePairs));
             return NO_ERROR;
-        } break;
+         } break;
+        case GET_PARAMETERS: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *ioHandle;
+            data.read(&ioHandle, sizeof(void *));
+            String8 keys(data.readString8());
+            reply->writeString8(getParameters(ioHandle, keys));
+            return NO_ERROR;
+         } break;
+
         case REGISTER_CLIENT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient>(data.readStrongBinder());
@@ -527,14 +634,93 @@
             reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) );
             return NO_ERROR;
         } break;
-        case WAKE_UP: {
+        case OPEN_OUTPUT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            wakeUp();
+            uint32_t devices = data.readInt32();
+            uint32_t samplingRate = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t channels = data.readInt32();
+            uint32_t latency = data.readInt32();
+            uint32_t flags = data.readInt32();
+            void *output = openOutput(&devices,
+                                     &samplingRate,
+                                     &format,
+                                     &channels,
+                                     &latency,
+                                     flags);
+            LOGV("OPEN_OUTPUT output, %p", output);
+            reply->write(&output, sizeof(void *));
+            reply->writeInt32(devices);
+            reply->writeInt32(samplingRate);
+            reply->writeInt32(format);
+            reply->writeInt32(channels);
+            reply->writeInt32(latency);
             return NO_ERROR;
         } break;
-        case IS_A2DP_ENABLED: {
+        case OPEN_DUPLICATE_OUTPUT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( (int)isA2dpEnabled() );
+            void *output1;
+            void *output2;
+            data.read(&output1, sizeof(void *));
+            data.read(&output2, sizeof(void *));
+            void *output = openDuplicateOutput(output1, output2);
+            reply->write(&output, sizeof(void *));
+            return NO_ERROR;
+        } break;
+        case CLOSE_OUTPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *output;
+            data.read(&output, sizeof(void *));
+            reply->writeInt32(closeOutput(output));
+            return NO_ERROR;
+        } break;
+        case SUSPEND_OUTPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *output;
+            data.read(&output, sizeof(void *));
+            reply->writeInt32(suspendOutput(output));
+            return NO_ERROR;
+        } break;
+        case RESTORE_OUTPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *output;
+            data.read(&output, sizeof(void *));
+            reply->writeInt32(restoreOutput(output));
+            return NO_ERROR;
+        } break;
+        case OPEN_INPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            uint32_t devices = data.readInt32();
+            uint32_t samplingRate = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t channels = data.readInt32();
+            uint32_t acoutics = data.readInt32();
+
+            void *input = openInput(&devices,
+                                     &samplingRate,
+                                     &format,
+                                     &channels,
+                                     acoutics);
+            reply->write(&input, sizeof(void *));
+            reply->writeInt32(devices);
+            reply->writeInt32(samplingRate);
+            reply->writeInt32(format);
+            reply->writeInt32(channels);
+            return NO_ERROR;
+        } break;
+        case CLOSE_INPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *input;
+            data.read(&input, sizeof(void *));
+            reply->writeInt32(closeInput(input));
+            return NO_ERROR;
+        } break;
+        case SET_STREAM_OUTPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *output;
+            uint32_t stream = data.readInt32();
+            data.read(&output, sizeof(void *));
+            reply->writeInt32(setStreamOutput(stream, output));
             return NO_ERROR;
         } break;
         default:
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 75699b4..eaae977 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -23,11 +23,12 @@
 #include <binder/Parcel.h>
 
 #include <media/IAudioFlingerClient.h>
+#include <media/AudioSystem.h>
 
 namespace android {
 
 enum {
-    AUDIO_OUTPUT_CHANGED = IBinder::FIRST_CALL_TRANSACTION
+    IO_CONFIG_CHANGED = IBinder::FIRST_CALL_TRANSACTION
 };
 
 class BpAudioFlingerClient : public BpInterface<IAudioFlingerClient>
@@ -38,12 +39,25 @@
     {
     }
 
-    void a2dpEnabledChanged(bool enabled)
+    void ioConfigChanged(int event, void *param1, void *param2)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
-        data.writeInt32((int)enabled);
-        remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+        data.writeInt32(event);
+        data.write(&param1, sizeof(void *));
+        if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
+            uint32_t stream = *(uint32_t *)param2;
+            LOGV("ioConfigChanged stream %d", stream);
+            data.writeInt32(stream);
+        } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+            AudioSystem::OutputDescriptor *desc = (AudioSystem::OutputDescriptor *)param2;
+            data.writeInt32(desc->samplingRate);
+            data.writeInt32(desc->format);
+            data.writeInt32(desc->channels);
+            data.writeInt32(desc->frameCount);
+            data.writeInt32(desc->latency);
+        }
+        remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
 
@@ -55,10 +69,27 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
-        case AUDIO_OUTPUT_CHANGED: {
+    case IO_CONFIG_CHANGED: {
             CHECK_INTERFACE(IAudioFlingerClient, data, reply);
-            bool enabled = (bool)data.readInt32();
-            a2dpEnabledChanged(enabled);
+            int event = data.readInt32();
+            void *param1;
+            void *param2 = 0;
+            AudioSystem::OutputDescriptor desc;
+            uint32_t stream;
+            data.read(&param1, sizeof(void *));
+            if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
+                stream = data.readInt32();
+                param2 = &stream;
+                LOGV("STREAM_CONFIG_CHANGED stream %d", stream);
+            } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+                desc.samplingRate = data.readInt32();
+                desc.format = data.readInt32();
+                desc.channels = data.readInt32();
+                desc.frameCount = data.readInt32();
+                desc.latency = data.readInt32();
+                param2 = &desc;
+            }
+            ioConfigChanged(event, param1, param2);
             return NO_ERROR;
         } break;
         default:
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
new file mode 100644
index 0000000..0d8a329
--- /dev/null
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -0,0 +1,423 @@
+/*
+**
+** Copyright 2009, 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.
+*/
+
+#define LOG_TAG "IAudioPolicyService"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IAudioPolicyService.h>
+
+namespace android {
+
+enum {
+    SET_DEVICE_CONNECTION_STATE = IBinder::FIRST_CALL_TRANSACTION,
+    GET_DEVICE_CONNECTION_STATE,
+    SET_PHONE_STATE,
+    SET_RINGER_MODE,
+    SET_FORCE_USE,
+    GET_FORCE_USE,
+    GET_OUTPUT,
+    START_OUTPUT,
+    STOP_OUTPUT,
+    RELEASE_OUTPUT,
+    GET_INPUT,
+    START_INPUT,
+    STOP_INPUT,
+    RELEASE_INPUT,
+    INIT_STREAM_VOLUME,
+    SET_STREAM_VOLUME,
+    GET_STREAM_VOLUME
+};
+
+class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
+{
+public:
+    BpAudioPolicyService(const sp<IBinder>& impl)
+        : BpInterface<IAudioPolicyService>(impl)
+    {
+    }
+
+    virtual status_t setDeviceConnectionState(
+                                    AudioSystem::audio_devices device,
+                                    AudioSystem::device_connection_state state,
+                                    const char *device_address)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(device));
+        data.writeInt32(static_cast <uint32_t>(state));
+        data.writeCString(device_address);
+        remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual AudioSystem::device_connection_state getDeviceConnectionState(
+                                    AudioSystem::audio_devices device,
+                                    const char *device_address)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(device));
+        data.writeCString(device_address);
+        remote()->transact(GET_DEVICE_CONNECTION_STATE, data, &reply);
+        return static_cast <AudioSystem::device_connection_state>(reply.readInt32());
+    }
+
+    virtual status_t setPhoneState(int state)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(state);
+        remote()->transact(SET_PHONE_STATE, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t setRingerMode(uint32_t mode, uint32_t mask)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        data.writeInt32(mask);
+        remote()->transact(SET_RINGER_MODE, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(usage));
+        data.writeInt32(static_cast <uint32_t>(config));
+        remote()->transact(SET_FORCE_USE, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(usage));
+        remote()->transact(GET_FORCE_USE, data, &reply);
+        return static_cast <AudioSystem::forced_config> (reply.readInt32());
+    }
+
+    virtual audio_io_handle_t getOutput(
+                                        AudioSystem::stream_type stream,
+                                        uint32_t samplingRate,
+                                        uint32_t format,
+                                        uint32_t channels,
+                                        AudioSystem::output_flags flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(stream));
+        data.writeInt32(samplingRate);
+        data.writeInt32(static_cast <uint32_t>(format));
+        data.writeInt32(channels);
+        data.writeInt32(static_cast <uint32_t>(flags));
+        remote()->transact(GET_OUTPUT, data, &reply);
+        audio_io_handle_t output;
+        reply.read(&output, sizeof(audio_io_handle_t));
+        return output;
+    }
+
+    virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&output, sizeof(audio_io_handle_t));
+        data.writeInt32(stream);
+        remote()->transact(START_OUTPUT, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&output, sizeof(audio_io_handle_t));
+        data.writeInt32(stream);
+        remote()->transact(STOP_OUTPUT, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual void releaseOutput(audio_io_handle_t output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&output, sizeof(audio_io_handle_t));
+        remote()->transact(RELEASE_OUTPUT, data, &reply);
+    }
+
+    virtual audio_io_handle_t getInput(
+                                    int inputSource,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::audio_in_acoustics acoustics)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(inputSource);
+        data.writeInt32(samplingRate);
+        data.writeInt32(static_cast <uint32_t>(format));
+        data.writeInt32(channels);
+        data.writeInt32(static_cast <uint32_t>(acoustics));
+        remote()->transact(GET_INPUT, data, &reply);
+        audio_io_handle_t input;
+        reply.read(&input, sizeof(audio_io_handle_t));
+        return input;
+    }
+
+    virtual status_t startInput(audio_io_handle_t input)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&input, sizeof(audio_io_handle_t));
+        remote()->transact(START_INPUT, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t stopInput(audio_io_handle_t input)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&input, sizeof(audio_io_handle_t));
+        remote()->transact(STOP_INPUT, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual void releaseInput(audio_io_handle_t input)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&input, sizeof(audio_io_handle_t));
+        remote()->transact(RELEASE_INPUT, data, &reply);
+    }
+
+    virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+                                    int indexMin,
+                                    int indexMax)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(stream));
+        data.writeInt32(indexMin);
+        data.writeInt32(indexMax);
+        remote()->transact(INIT_STREAM_VOLUME, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(stream));
+        data.writeInt32(index);
+        remote()->transact(SET_STREAM_VOLUME, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(stream));
+        remote()->transact(GET_STREAM_VOLUME, data, &reply);
+        int lIndex = reply.readInt32();
+        if (index) *index = lIndex;
+        return static_cast <status_t> (reply.readInt32());
+    }
+};
+
+IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
+
+// ----------------------------------------------------------------------
+
+
+status_t BnAudioPolicyService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case SET_DEVICE_CONNECTION_STATE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::audio_devices device = static_cast <AudioSystem::audio_devices>(data.readInt32());
+            AudioSystem::device_connection_state state = static_cast <AudioSystem::device_connection_state>(data.readInt32());
+            const char *device_address = data.readCString();
+            reply->writeInt32(static_cast <uint32_t>(setDeviceConnectionState(device, state, device_address)));
+            return NO_ERROR;
+        } break;
+
+        case GET_DEVICE_CONNECTION_STATE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::audio_devices device = static_cast <AudioSystem::audio_devices>(data.readInt32());
+            const char *device_address = data.readCString();
+            reply->writeInt32(static_cast <uint32_t>(getDeviceConnectionState(device, device_address)));
+            return NO_ERROR;
+        } break;
+
+        case SET_PHONE_STATE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            reply->writeInt32(static_cast <uint32_t>(setPhoneState(data.readInt32())));
+            return NO_ERROR;
+        } break;
+
+        case SET_RINGER_MODE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            uint32_t mode = data.readInt32();
+            uint32_t mask = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(setRingerMode(mode, mask)));
+            return NO_ERROR;
+        } break;
+
+        case SET_FORCE_USE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::force_use usage = static_cast <AudioSystem::force_use>(data.readInt32());
+            AudioSystem::forced_config config = static_cast <AudioSystem::forced_config>(data.readInt32());
+            reply->writeInt32(static_cast <uint32_t>(setForceUse(usage, config)));
+            return NO_ERROR;
+        } break;
+
+        case GET_FORCE_USE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::force_use usage = static_cast <AudioSystem::force_use>(data.readInt32());
+            reply->writeInt32(static_cast <uint32_t>(getForceUse(usage)));
+            return NO_ERROR;
+        } break;
+
+        case GET_OUTPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            uint32_t samplingRate = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t channels = data.readInt32();
+            AudioSystem::output_flags flags = static_cast <AudioSystem::output_flags>(data.readInt32());
+
+            audio_io_handle_t output = getOutput(stream,
+                                                 samplingRate,
+                                                 format,
+                                                 channels,
+                                                 flags);
+            reply->write(&output, sizeof(audio_io_handle_t));
+            return NO_ERROR;
+        } break;
+
+        case START_OUTPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t output;
+            data.read(&output, sizeof(audio_io_handle_t));
+            uint32_t stream = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(startOutput(output, (AudioSystem::stream_type)stream)));
+            return NO_ERROR;
+        } break;
+
+        case STOP_OUTPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t output;
+            data.read(&output, sizeof(audio_io_handle_t));
+            uint32_t stream = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(stopOutput(output, (AudioSystem::stream_type)stream)));
+            return NO_ERROR;
+        } break;
+
+        case RELEASE_OUTPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t output;
+            data.read(&output, sizeof(audio_io_handle_t));
+            releaseOutput(output);
+            return NO_ERROR;
+        } break;
+
+        case GET_INPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            int inputSource = data.readInt32();
+            uint32_t samplingRate = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t channels = data.readInt32();
+            AudioSystem::audio_in_acoustics acoustics = static_cast <AudioSystem::audio_in_acoustics>(data.readInt32());
+            audio_io_handle_t input = getInput(inputSource,
+                                               samplingRate,
+                                               format,
+                                               channels,
+                                               acoustics);
+            reply->write(&input, sizeof(audio_io_handle_t));
+            return NO_ERROR;
+        } break;
+
+        case START_INPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t input;
+            data.read(&input, sizeof(audio_io_handle_t));
+            reply->writeInt32(static_cast <uint32_t>(startInput(input)));
+            return NO_ERROR;
+        } break;
+
+        case STOP_INPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t input;
+            data.read(&input, sizeof(audio_io_handle_t));
+            reply->writeInt32(static_cast <uint32_t>(stopInput(input)));
+            return NO_ERROR;
+        } break;
+
+        case RELEASE_INPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t input;
+            data.read(&input, sizeof(audio_io_handle_t));
+            releaseInput(input);
+            return NO_ERROR;
+        } break;
+
+        case INIT_STREAM_VOLUME: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            int indexMin = data.readInt32();
+            int indexMax = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(initStreamVolume(stream, indexMin,indexMax)));
+            return NO_ERROR;
+        } break;
+
+        case SET_STREAM_VOLUME: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            int index = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream, index)));
+            return NO_ERROR;
+        } break;
+
+        case GET_STREAM_VOLUME: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            int index;
+            status_t status = getStreamVolumeIndex(stream, &index);
+            reply->writeInt32(index);
+            reply->writeInt32(static_cast <uint32_t>(status));
+            return NO_ERROR;
+        } break;
+
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index 586aacb..ee9e1d8 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -99,7 +99,7 @@
     mAudioTrack->set(AudioSystem::MUSIC,  //TODO parametrize this
             pLibConfig->sampleRate,
             1, // format = PCM 16bits per sample,
-            pLibConfig->numChannels,
+            (pLibConfig->numChannels == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
             mTrackBufferSize,
             0);
 
diff --git a/media/libmedia/Metadata.cpp b/media/libmedia/Metadata.cpp
new file mode 100644
index 0000000..35ec6b3
--- /dev/null
+++ b/media/libmedia/Metadata.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Metadata"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <media/Metadata.h>
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+// This file contains code to serialize Metadata triples (key, type,
+// value) into a parcel. The Parcel is destinated to be decoded by the
+// Metadata.java class.
+
+namespace {
+// All these constants below must be kept in sync with Metadata.java.
+enum MetadataId {
+    FIRST_SYSTEM_ID = 1,
+    LAST_SYSTEM_ID = 31,
+    FIRST_CUSTOM_ID = 8192
+};
+
+// Types
+enum Types {
+    STRING_VAL = 1,
+    INTEGER_VAL,
+    BOOLEAN_VAL,
+    LONG_VAL,
+    DOUBLE_VAL,
+    TIMED_TEXT_VAL,
+    DATE_VAL,
+    BYTE_ARRAY_VAL,
+};
+
+const size_t kRecordHeaderSize = 3 * sizeof(int32_t);
+const int32_t kMetaMarker = 0x4d455441;  // 'M' 'E' 'T' 'A'
+
+}  // anonymous namespace
+
+namespace android {
+namespace media {
+
+Metadata::Metadata(Parcel *p)
+    :mData(p),
+     mBegin(p->dataPosition()) { }
+
+Metadata::~Metadata() { }
+
+void Metadata::resetParcel()
+{
+    mData->setDataPosition(mBegin);
+}
+
+// Update the 4 bytes int at the beginning of the parcel which holds
+// the number of bytes written so far.
+void Metadata::updateLength()
+{
+    const size_t end = mData->dataPosition();
+
+    mData->setDataPosition(mBegin);
+    mData->writeInt32(end - mBegin);
+    mData->setDataPosition(end);
+}
+
+// Write the header. The java layer will look for the marker.
+bool Metadata::appendHeader()
+{
+    bool ok = true;
+
+    // Placeholder for the length of the metadata
+    ok = ok && mData->writeInt32(-1) == OK;
+    ok = ok && mData->writeInt32(kMetaMarker) == OK;
+    return ok;
+}
+
+bool Metadata::appendBool(int key, bool val)
+{
+    if (!checkKey(key)) {
+        return false;
+    }
+
+    const size_t begin = mData->dataPosition();
+    bool ok = true;
+
+    // 4 int32s: size, key, type, value.
+    ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
+    ok = ok && mData->writeInt32(key) == OK;
+    ok = ok && mData->writeInt32(BOOLEAN_VAL) == OK;
+    ok = ok && mData->writeInt32(val ? 1 : 0) == OK;
+    if (!ok) {
+        mData->setDataPosition(begin);
+    }
+    return ok;
+}
+
+bool Metadata::appendInt32(int key, int32_t val)
+{
+    if (!checkKey(key)) {
+        return false;
+    }
+
+    const size_t begin = mData->dataPosition();
+    bool ok = true;
+
+    // 4 int32s: size, key, type, value.
+    ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
+    ok = ok && mData->writeInt32(key) == OK;
+    ok = ok && mData->writeInt32(INTEGER_VAL) == OK;
+    ok = ok && mData->writeInt32(val) == OK;
+    if (!ok) {
+        mData->setDataPosition(begin);
+    }
+    return ok;
+}
+
+// Check the key (i.e metadata id) is valid if it is a system one.
+// Loop over all the exiting ones in the Parcel to check for duplicate
+// (not allowed).
+bool Metadata::checkKey(int key)
+{
+    if (key < FIRST_SYSTEM_ID ||
+        (LAST_SYSTEM_ID < key && key < FIRST_CUSTOM_ID)) {
+        LOGE("Bad key %d", key);
+        return false;
+    }
+    size_t curr = mData->dataPosition();
+    // Loop over the keys to check if it has been used already.
+    mData->setDataPosition(mBegin);
+
+    bool error = false;
+    size_t left = curr - mBegin;
+    while (left > 0) {
+        size_t pos = mData->dataPosition();
+        size_t size = mData->readInt32();
+        if (size < kRecordHeaderSize || size > left) {
+            error = true;
+            break;
+        }
+        if (mData->readInt32() == key) {
+            LOGE("Key exists already %d", key);
+            error = true;
+            break;
+        }
+        mData->setDataPosition(pos + size);
+        left -= size;
+    }
+    mData->setDataPosition(curr);
+    return !error;
+}
+
+}  // namespace android::media
+}  // namespace android
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 5435da7..3ea64ae 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -1001,7 +1001,7 @@
 
    // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
     mpAudioTrack
-            = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, 0, 0, audioCallback, this, 0);
+            = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, AudioSystem::CHANNEL_OUT_MONO, 0, 0, audioCallback, this, 0);
 
     if (mpAudioTrack == 0) {
         LOGE("AudioTrack allocation failed");
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 5e62f9d..1d960c5 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -47,10 +47,9 @@
 #include <media/MediaPlayerInterface.h>
 #include <media/mediarecorder.h>
 #include <media/MediaMetadataRetrieverInterface.h>
+#include <media/Metadata.h>
 #include <media/AudioTrack.h>
 
-#include <utils/SortedVector.h>
-
 #include "MediaRecorderClient.h"
 #include "MediaPlayerService.h"
 #include "MetadataRetrieverClient.h"
@@ -85,21 +84,17 @@
 #endif
 
 namespace {
+using android::media::Metadata;
 using android::status_t;
 using android::OK;
 using android::BAD_VALUE;
 using android::NOT_ENOUGH_DATA;
-using android::MetadataType;
 using android::Parcel;
-using android::SortedVector;
 
 // Max number of entries in the filter.
 const int kMaxFilterSize = 64;  // I pulled that out of thin air.
 
-// Keep in sync with ANY in Metadata.java
-const int32_t kAny = 0;
-
-const int32_t kMetaMarker = 0x4d455441;  // 'M' 'E' 'T' 'A'
+// FIXME: Move all the metadata related function in the Metadata.cpp
 
 
 // Unmarshall a filter from a Parcel.
@@ -124,7 +119,7 @@
 // @param[out] status On exit contains the status code to be returned.
 // @return true if the parcel starts with a valid filter.
 bool unmarshallFilter(const Parcel& p,
-                      SortedVector<MetadataType> *filter,
+                      Metadata::Filter *filter,
                       status_t *status)
 {
     int32_t val;
@@ -147,7 +142,7 @@
     filter->clear();
     filter->setCapacity(num);
 
-    size_t size = num * sizeof(MetadataType);
+    size_t size = num * sizeof(Metadata::Type);
 
 
     if (p.dataAvail() < size)
@@ -157,7 +152,8 @@
         return false;
     }
 
-    const MetadataType *data = static_cast<const MetadataType*>(p.readInplace(size));
+    const Metadata::Type *data =
+            static_cast<const Metadata::Type*>(p.readInplace(size));
 
     if (NULL == data)
     {
@@ -181,11 +177,11 @@
 // @param filter Of metadata type.
 // @param val To be searched.
 // @return true if a match was found.
-bool findMetadata(const SortedVector<MetadataType>& filter, const int32_t val)
+bool findMetadata(const Metadata::Filter& filter, const int32_t val)
 {
     // Deal with empty and ANY right away
     if (filter.isEmpty()) return false;
-    if (filter[0] == kAny) return true;
+    if (filter[0] == Metadata::kAny) return true;
 
     return filter.indexOf(val) >= 0;
 }
@@ -857,7 +853,7 @@
 status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
 {
     status_t status;
-    SortedVector<MetadataType> allow, drop;
+    media::Metadata::Filter allow, drop;
 
     if (unmarshallFilter(filter, &allow, &status) &&
         unmarshallFilter(filter, &drop, &status)) {
@@ -872,14 +868,14 @@
 status_t MediaPlayerService::Client::getMetadata(
         bool update_only, bool apply_filter, Parcel *reply)
 {
-    sp<MediaPlayerBase> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
+    sp<MediaPlayerBase> player = getPlayer();
+    if (player == 0) return UNKNOWN_ERROR;
 
     status_t status;
     // Placeholder for the return code, updated by the caller.
     reply->writeInt32(-1);
 
-    SortedVector<MetadataType> ids;
+    media::Metadata::Filter ids;
 
     // We don't block notifications while we fetch the data. We clear
     // mMetadataUpdated first so we don't lose notifications happening
@@ -892,14 +888,13 @@
         mMetadataUpdated.clear();
     }
 
-    const size_t begin = reply->dataPosition();
-    reply->writeInt32(-1);  // Placeholder for the length of the metadata
-    reply->writeInt32(kMetaMarker);
+    media::Metadata metadata(reply);
 
-    status = p->getMetadata(ids, reply);
+    metadata.appendHeader();
+    status = player->getMetadata(ids, reply);
 
     if (status != OK) {
-        reply->setDataPosition(begin);
+        metadata.resetParcel();
         LOGE("getMetadata failed %d", status);
         return status;
     }
@@ -908,12 +903,8 @@
     // filtering takes place on the update notifications already. This
     // would be when all the metadata are fetch and a filter is set.
 
-    const size_t end = reply->dataPosition();
-
     // Everything is fine, update the metadata length.
-    reply->setDataPosition(begin);
-    reply->writeInt32(end - begin);
-    reply->setDataPosition(end);
+    metadata.updateLength();
     return OK;
 }
 
@@ -1043,7 +1034,7 @@
 
     if (MEDIA_INFO == msg &&
         MEDIA_INFO_METADATA_UPDATE == ext1) {
-        const MetadataType metadata_type = ext2;
+        const media::Metadata::Type metadata_type = ext2;
 
         if(client->shouldDropMetadata(metadata_type)) {
             return;
@@ -1058,7 +1049,7 @@
 }
 
 
-bool MediaPlayerService::Client::shouldDropMetadata(MetadataType code) const
+bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
 {
     Mutex::Autolock lock(mLock);
 
@@ -1074,7 +1065,7 @@
 }
 
 
-void MediaPlayerService::Client::addNewMetadataUpdate(MetadataType metadata_type) {
+void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
     Mutex::Autolock lock(mLock);
     if (mMetadataUpdated.indexOf(metadata_type) < 0) {
         mMetadataUpdated.add(metadata_type);
@@ -1319,11 +1310,21 @@
     AudioTrack *t;
     if (mCallback != NULL) {
         t = new AudioTrack(
-                mStreamType, sampleRate, format, channelCount, frameCount,
-                0 /* flags */, CallbackWrapper, this);
+                mStreamType,
+                sampleRate,
+                format,
+                (channelCount == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
+                frameCount,
+                0 /* flags */,
+                CallbackWrapper,
+                this);
     } else {
         t = new AudioTrack(
-                mStreamType, sampleRate, format, channelCount, frameCount);
+                mStreamType,
+                sampleRate,
+                format,
+                (channelCount == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
+                frameCount);
     }
 
     if ((t == 0) || (t->initCheck() != NO_ERROR)) {
@@ -1499,4 +1500,4 @@
     p->mSignal.signal();
 }
 
-}; // namespace android
+} // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 94cb917..a4be414 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -23,15 +23,14 @@
 #include <utils/List.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
-#include <utils/SortedVector.h>
 #include <utils/Vector.h>
 #include <ui/SurfaceComposerClient.h>
 
 #include <media/IMediaPlayerService.h>
 #include <media/MediaPlayerInterface.h>
+#include <media/Metadata.h>
 
 namespace android {
-typedef int32_t MetadataType;
 
 class IMediaRecorder;
 class IMediaMetadataRetriever;
@@ -239,12 +238,12 @@
         // @param type Of the metadata to be tested.
         // @return true if the metadata should be dropped according to
         //              the filters.
-        bool shouldDropMetadata(MetadataType type) const;
+        bool shouldDropMetadata(media::Metadata::Type type) const;
 
         // Add a new element to the set of metadata updated. Noop if
         // the element exists already.
         // @param type Of the metadata to be recorded.
-        void addNewMetadataUpdate(MetadataType type);
+        void addNewMetadataUpdate(media::Metadata::Type type);
 
         mutable     Mutex                       mLock;
                     sp<MediaPlayerBase>         mPlayer;
@@ -257,14 +256,14 @@
                     int32_t                     mConnId;
 
         // Metadata filters.
-        SortedVector<int32_t>       mMetadataAllow;  // protected by mLock
-        SortedVector<int32_t>       mMetadataDrop;  // protected by mLock
+        media::Metadata::Filter mMetadataAllow;  // protected by mLock
+        media::Metadata::Filter mMetadataDrop;  // protected by mLock
 
         // Metadata updated. For each MEDIA_INFO_METADATA_UPDATE
         // notification we try to update mMetadataUpdated which is a
         // set: no duplicate.
         // getMetadata clears this set.
-        SortedVector<int32_t>       mMetadataUpdated;  // protected by mLock
+        media::Metadata::Filter mMetadataUpdated;  // protected by mLock
 
 #if CALLBACK_ANTAGONIZER
                     Antagonizer*                mAntagonizer;
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index 30b6a2e..25d4a1b 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -49,10 +49,6 @@
     virtual status_t    invoke(const Parcel& request, Parcel *reply) {
         return INVALID_OPERATION;
     }
-    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
-                                    Parcel *records)  {
-        return INVALID_OPERATION;
-    }
 
 private:
             status_t    createOutputTrack();
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 8597275..9a06d13 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -144,7 +144,7 @@
     if (mPlayer == NULL) {
         return NO_INIT;
     }
-    
+
     status_t err = mPlayer->seekTo((int64_t)msec * 1000);
 
     sendEvent(MEDIA_SEEK_COMPLETE);
@@ -205,9 +205,4 @@
     }
 }
 
-status_t StagefrightPlayer::getMetadata(
-        const SortedVector<MetadataType> &ids, Parcel *records) {
-    return INVALID_OPERATION;
-}
-
 }  // namespace android
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index f93c1f8..f214872c 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -48,9 +48,6 @@
     virtual status_t invoke(const Parcel &request, Parcel *reply);
     virtual void setAudioSink(const sp<AudioSink> &audioSink);
 
-    virtual status_t getMetadata(
-            const SortedVector<MetadataType> &ids, Parcel *records);
-
 private:
     MediaPlayerImpl *mPlayer;
 
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index 339b108..80d53a8 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -94,10 +94,6 @@
     virtual status_t invoke(const android::Parcel& in, android::Parcel *out) {
         return mPlayer->invoke(in, out);
     }
-    virtual status_t getMetadata(const SortedVector<MetadataType>& ids,
-                                 Parcel *records) {
-        return INVALID_OPERATION;
-    }
 
 
     // @return true if the current build is 'eng' or 'test' and the
diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h
index 040eb36..4024654 100644
--- a/media/libmediaplayerservice/VorbisPlayer.h
+++ b/media/libmediaplayerservice/VorbisPlayer.h
@@ -54,10 +54,6 @@
     virtual status_t    setLooping(int loop);
     virtual player_type playerType() { return VORBIS_PLAYER; }
     virtual status_t    invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
-    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
-                                    Parcel *records)  {
-        return INVALID_OPERATION;
-    }
 
 private:
             status_t    setdatasource(const char *path, int fd, int64_t offset, int64_t length);
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index fbea0d4..7094cfa 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -28,6 +28,7 @@
 #include <AudioFlinger.h>
 #include <CameraService.h>
 #include <MediaPlayerService.h>
+#include <AudioPolicyService.h>
 #include <private/android_filesystem_config.h>
 
 using namespace android;
@@ -40,6 +41,7 @@
     AudioFlinger::instantiate();
     MediaPlayerService::instantiate();
     CameraService::instantiate();
+    AudioPolicyService::instantiate();
     ProcessState::self()->startThreadPool();
     IPCThreadState::self()->joinThreadPool();
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
index aefedc3..cea3a5a 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
@@ -140,7 +140,7 @@
         
         TestResults res = constructorTestMultiSampleRate(
                 AudioManager.STREAM_MUSIC, AudioTrack.MODE_STREAM, 
-                    AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
+                    AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
                 AudioTrack.STATE_INITIALIZED);
 
         assertTrue("testConstructorMono16MusicStream: " + res.mResultLog, res.mResult);
@@ -153,7 +153,7 @@
         
         TestResults res = constructorTestMultiSampleRate(
                 AudioManager.STREAM_MUSIC, AudioTrack.MODE_STREAM, 
-                    AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT,
+                    AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
                 AudioTrack.STATE_INITIALIZED);
 
         assertTrue("testConstructorStereo16MusicStream: " + res.mResultLog, res.mResult);
@@ -166,7 +166,7 @@
         
         TestResults res = constructorTestMultiSampleRate(
                 AudioManager.STREAM_MUSIC, AudioTrack.MODE_STATIC, 
-                    AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
+                    AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
                 AudioTrack.STATE_NO_STATIC_DATA);
 
         assertTrue("testConstructorMono16MusicStatic: " + res.mResultLog, res.mResult);
@@ -179,7 +179,7 @@
         
         TestResults res = constructorTestMultiSampleRate(
                 AudioManager.STREAM_MUSIC, AudioTrack.MODE_STATIC, 
-                    AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT,
+                    AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
                 AudioTrack.STATE_NO_STATIC_DATA);
 
         assertTrue("testConstructorStereo16MusicStatic: " + res.mResultLog, res.mResult);
@@ -196,7 +196,7 @@
         
         TestResults res = constructorTestMultiSampleRate(
                 AudioManager.STREAM_MUSIC, AudioTrack.MODE_STREAM, 
-                    AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_8BIT,
+                    AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_8BIT,
                 AudioTrack.STATE_INITIALIZED);
 
         assertTrue("testConstructorMono8MusicStream: " + res.mResultLog, res.mResult);
@@ -208,7 +208,7 @@
         
         TestResults res = constructorTestMultiSampleRate(
                 AudioManager.STREAM_MUSIC, AudioTrack.MODE_STREAM, 
-                    AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_8BIT,
+                    AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_8BIT,
                 AudioTrack.STATE_INITIALIZED);
 
         assertTrue("testConstructorStereo8MusicStream: " + res.mResultLog, res.mResult);
@@ -220,7 +220,7 @@
         
         TestResults res = constructorTestMultiSampleRate(
                 AudioManager.STREAM_MUSIC, AudioTrack.MODE_STATIC, 
-                    AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_8BIT,
+                    AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_8BIT,
                 AudioTrack.STATE_NO_STATIC_DATA);
 
         assertTrue("testConstructorMono8MusicStatic: " + res.mResultLog, res.mResult);
@@ -232,7 +232,7 @@
         
         TestResults res = constructorTestMultiSampleRate(
                 AudioManager.STREAM_MUSIC, AudioTrack.MODE_STATIC, 
-                    AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_8BIT,
+                    AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_8BIT,
                 AudioTrack.STATE_NO_STATIC_DATA);
 
         assertTrue("testConstructorStereo8MusicStatic: " + res.mResultLog, res.mResult);
@@ -248,15 +248,15 @@
     public void testConstructorStreamType() throws Exception {
         // constants for test
         final int TYPE_TEST_SR = 22050;
-        final int TYPE_TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TYPE_TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TYPE_TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TYPE_TEST_MODE = AudioTrack.MODE_STREAM;
         final int[] STREAM_TYPES = { AudioManager.STREAM_ALARM, AudioManager.STREAM_BLUETOOTH_SCO, 
                 AudioManager.STREAM_MUSIC, AudioManager.STREAM_NOTIFICATION,
                 AudioManager.STREAM_RING, AudioManager.STREAM_SYSTEM, 
-                AudioManager.STREAM_VOICE_CALL };
+                AudioManager.STREAM_VOICE_CALL, AudioManager.STREAM_DTMF, };
         final String[] STREAM_NAMES = { "STREAM_ALARM", "STREAM_BLUETOOTH_SCO", "STREAM_MUSIC",
-                "STREAM_NOTIFICATION", "STREAM_RING", "STREAM_SYSTEM", "STREAM_VOICE_CALL" };
+                "STREAM_NOTIFICATION", "STREAM_RING", "STREAM_SYSTEM", "STREAM_VOICE_CALL", "STREAM_DTMF" };
         
         boolean localTestRes = true;
         AudioTrack track = null;
@@ -303,7 +303,7 @@
         // constants for test
         final String TEST_NAME = "testPlaybackHeadPositionAfterInit";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -324,7 +324,7 @@
         // constants for test
         final String TEST_NAME = "testPlaybackHeadPositionIncrease";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -352,7 +352,7 @@
         // constants for test
         final String TEST_NAME = "testPlaybackHeadPositionAfterFlush";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -382,7 +382,7 @@
         // constants for test
         final String TEST_NAME = "testPlaybackHeadPositionAfterStop";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -413,7 +413,7 @@
         // constants for test
         final String TEST_NAME = "testPlaybackHeadPositionAfterPause";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -448,7 +448,7 @@
         // constants for test
         final String TEST_NAME = "testSetStereoVolumeMax";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -474,7 +474,7 @@
         // constants for test
         final String TEST_NAME = "testSetStereoVolumeMin";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -500,7 +500,7 @@
         // constants for test
         final String TEST_NAME = "testSetStereoVolumeMid";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -526,7 +526,7 @@
         // constants for test
         final String TEST_NAME = "testSetPlaybackRate";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -552,7 +552,7 @@
         // constants for test
         final String TEST_NAME = "testSetPlaybackRateZero";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -574,7 +574,7 @@
         // constants for test
         final String TEST_NAME = "testSetPlaybackRateTwiceOutputSR";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -601,7 +601,7 @@
         // constants for test
         final String TEST_NAME = "testSetGetPlaybackRate";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -628,7 +628,7 @@
         // constants for test
         final String TEST_NAME = "testSetPlaybackRateUninit";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STATIC;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -655,7 +655,7 @@
         // constants for test
         final String TEST_NAME = "testSetPlaybackHeadPositionPlaying";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -682,7 +682,7 @@
         // constants for test
         final String TEST_NAME = "testSetPlaybackHeadPositionStopped";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -710,7 +710,7 @@
         // constants for test
         final String TEST_NAME = "testSetPlaybackHeadPositionPaused";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -738,7 +738,7 @@
         // constants for test
         final String TEST_NAME = "testSetPlaybackHeadPositionTooFar";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -770,7 +770,7 @@
         // constants for test
         final String TEST_NAME = "testSetLoopPointsStream";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -794,7 +794,7 @@
         // constants for test
         final String TEST_NAME = "testSetLoopPointsStartAfterEnd";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STATIC;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -818,7 +818,7 @@
         // constants for test
         final String TEST_NAME = "testSetLoopPointsSuccess";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STATIC;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -842,7 +842,7 @@
         // constants for test
         final String TEST_NAME = "testSetLoopPointsLoopTooLong";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STATIC;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -868,7 +868,7 @@
         // constants for test
         final String TEST_NAME = "testSetLoopPointsStartTooFar";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STATIC;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -896,7 +896,7 @@
         // constants for test
         final String TEST_NAME = "testSetLoopPointsEndTooFar";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STATIC;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -929,7 +929,7 @@
         // constants for test
         final String TEST_NAME = "testWriteByteOffsetTooBig";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -953,7 +953,7 @@
         // constants for test
         final String TEST_NAME = "testWriteShortOffsetTooBig";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -977,7 +977,7 @@
         // constants for test
         final String TEST_NAME = "testWriteByteSizeTooBig";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1001,7 +1001,7 @@
         // constants for test
         final String TEST_NAME = "testWriteShortSizeTooBig";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1025,7 +1025,7 @@
         // constants for test
         final String TEST_NAME = "testWriteByteNegativeOffset";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1049,7 +1049,7 @@
         // constants for test
         final String TEST_NAME = "testWriteShortNegativeOffset";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1073,7 +1073,7 @@
         // constants for test
         final String TEST_NAME = "testWriteByteNegativeSize";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1097,7 +1097,7 @@
         // constants for test
         final String TEST_NAME = "testWriteShortNegativeSize";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1121,7 +1121,7 @@
         // constants for test
         final String TEST_NAME = "testWriteByte";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1145,7 +1145,7 @@
         // constants for test
         final String TEST_NAME = "testWriteShort";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1169,7 +1169,7 @@
         // constants for test
         final String TEST_NAME = "testWriteByte8bit";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1193,7 +1193,7 @@
         // constants for test
         final String TEST_NAME = "testWriteShort8bit";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1221,7 +1221,7 @@
       // constant for test
       final String TEST_NAME = "testGetMinBufferSizeTooLowSR";
       final int TEST_SR = 3999;
-      final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+      final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
       final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
       final int TEST_MODE = AudioTrack.MODE_STREAM;
       final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
@@ -1238,7 +1238,7 @@
       // constant for testg
       final String TEST_NAME = "testGetMinBufferSizeTooHighSR";
       final int TEST_SR = 48001;
-      final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+      final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
       final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
       final int TEST_MODE = AudioTrack.MODE_STREAM;
       final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp
index 8d575a3..77bb5b2 100644
--- a/media/tests/players/invoke_mock_media_player.cpp
+++ b/media/tests/players/invoke_mock_media_player.cpp
@@ -27,7 +27,6 @@
 using android::INVALID_OPERATION;
 using android::ISurface;
 using android::MediaPlayerBase;
-using android::MetadataType;
 using android::OK;
 using android::Parcel;
 using android::SortedVector;
@@ -78,8 +77,6 @@
     virtual status_t    setLooping(int loop) {return OK;}
     virtual player_type playerType() {return TEST_PLAYER;}
     virtual status_t    invoke(const Parcel& request, Parcel *reply);
-    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
-                                    Parcel *records) {return INVALID_OPERATION;}
 
   private:
     // Take a request, copy it to the reply.
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 2b888e4..f00fd39 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -64,7 +64,7 @@
 
     private static final String TAG = "SettingsProvider";
     private static final String DATABASE_NAME = "settings.db";
-    private static final int DATABASE_VERSION = 36;
+    private static final int DATABASE_VERSION = 37;
 
     private Context mContext;
 
@@ -414,7 +414,27 @@
             }
             upgradeVersion = 36;
         }
-        
+        if (upgradeVersion == 36) {
+           // This upgrade adds the STREAM_SYSTEM_ENFORCED type to the list of
+            // types affected by ringer modes (silent, vibrate, etc.)
+            db.beginTransaction();
+            try {
+                db.execSQL("DELETE FROM system WHERE name='"
+                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
+                int newValue = (1 << AudioManager.STREAM_RING)
+                        | (1 << AudioManager.STREAM_NOTIFICATION)
+                        | (1 << AudioManager.STREAM_SYSTEM)
+                        | (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
+                db.execSQL("INSERT INTO system ('name', 'value') values ('"
+                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
+                        + String.valueOf(newValue) + "')");
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+            }
+            upgradeVersion = 36;
+        }
+
         if (upgradeVersion != currentVersion) {
             Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
                     + ", must wipe the settings provider");
@@ -575,7 +595,7 @@
         // By default, only the ring/notification and system streams are affected
         loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED,
                 (1 << AudioManager.STREAM_RING) | (1 << AudioManager.STREAM_NOTIFICATION) |
-                (1 << AudioManager.STREAM_SYSTEM));
+                (1 << AudioManager.STREAM_SYSTEM) | (1 << AudioManager.STREAM_SYSTEM_ENFORCED));
 
         loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED,
                 ((1 << AudioManager.STREAM_MUSIC) |
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index 99d7723..a4090cf 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -71,7 +71,7 @@
         AudioTrack*               mAudioOut;
         AudioSystem::stream_type  mStreamType;
         uint32_t                  mSampleRate;
-        AudioSystem::audio_format mAudFormat;
+        uint32_t                  mAudFormat;
         int                       mNbChannels;
         int8_t *                  mBuffer;
         size_t                    mBufferSize;
@@ -118,7 +118,6 @@
             mSampleRate = rate;
             mAudFormat  = format;
             mNbChannels = channel;
-
             mStreamType = streamType;
 
             // retrieve system properties to ensure successful creation of the
@@ -139,7 +138,8 @@
             if (minBufCount < 2) minBufCount = 2;
             int minFrameCount = (afFrameCount * rate * minBufCount)/afSampleRate;
 
-            mAudioOut = new AudioTrack(mStreamType, rate, format, channel,
+            mAudioOut = new AudioTrack(mStreamType, rate, format,
+                    (channel == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
                     minFrameCount > 4096 ? minFrameCount : 4096,
                     0, 0, 0, 0); // not using an AudioTrack callback
 
@@ -182,7 +182,7 @@
  * Directly speaks using AudioTrack or write to file
  */
 static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate,
-                           AudioSystem::audio_format format, int channel,
+                           uint32_t format, int channel,
                            int8_t *&wav, size_t &bufferSize, tts_synth_status status) {
     //LOGV("ttsSynthDoneCallback: %d bytes", bufferSize);
 
@@ -202,7 +202,7 @@
         }
 
         if (bufferSize > 0) {
-            prepAudioTrack(pJniData, pForAfter->streamType, rate, format, channel);
+            prepAudioTrack(pJniData, pForAfter->streamType, rate, (AudioSystem::audio_format)format, channel);
             if (pJniData->mAudioOut) {
                 pJniData->mAudioOut->write(wav, bufferSize);
                 memset(wav, 0, bufferSize);
diff --git a/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java b/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java
deleted file mode 100644
index e4c070f..0000000
--- a/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
-import android.net.vpn.VpnManager;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Proxy to start, stop and interact with an Android service defined in init.rc.
- * The android service is expected to accept connection through Unix domain
- * socket. When the proxy successfully starts the service, it will establish a
- * socket connection with the service. The socket serves two purposes: (1) send
- * commands to the service; (2) for the proxy to know whether the service is
- * alive.
- *
- * After the service receives commands from the proxy, it should return either
- * 0 if the service will close the socket (and the proxy will re-establish
- * another connection immediately after), or 1 if the socket is remained alive.
- */
-public class AndroidServiceProxy extends ProcessProxy {
-    private static final int WAITING_TIME = 15; // sec
-
-    private static final String SVC_STATE_CMD_PREFIX = "init.svc.";
-    private static final String SVC_START_CMD = "ctl.start";
-    private static final String SVC_STOP_CMD = "ctl.stop";
-    private static final String SVC_STATE_RUNNING = "running";
-    private static final String SVC_STATE_STOPPED = "stopped";
-
-    private static final int END_OF_ARGUMENTS = 255;
-
-    private static final int STOP_SERVICE = -1;
-    private static final int AUTH_ERROR_CODE = 51;
-
-    private String mServiceName;
-    private String mSocketName;
-    private LocalSocket mKeepaliveSocket;
-    private boolean mControlSocketInUse;
-    private Integer mSocketResult = null;
-    private String mTag;
-
-    /**
-     * Creates a proxy with the service name.
-     * @param serviceName the service name
-     */
-    public AndroidServiceProxy(String serviceName) {
-        mServiceName = serviceName;
-        mSocketName = serviceName;
-        mTag = "SProxy_" + serviceName;
-    }
-
-    @Override
-    public String getName() {
-        return "Service " + mServiceName;
-    }
-
-    @Override
-    public synchronized void stop() {
-        if (isRunning()) {
-            try {
-                setResultAndCloseControlSocket(STOP_SERVICE);
-            } catch (IOException e) {
-                // should not occur
-                throw new RuntimeException(e);
-            }
-        }
-        Log.d(mTag, "-----  Stop: " + mServiceName);
-        SystemProperties.set(SVC_STOP_CMD, mServiceName);
-    }
-
-    /**
-     * Sends a command with arguments to the service through the control socket.
-     */
-    public synchronized void sendCommand(String ...args) throws IOException {
-        OutputStream out = getControlSocketOutput();
-        for (String arg : args) outputString(out, arg);
-        out.write(END_OF_ARGUMENTS);
-        out.flush();
-        checkSocketResult();
-    }
-
-    /**
-     * {@inheritDoc}
-     * The method returns when the service exits.
-     */
-    @Override
-    protected void performTask() throws IOException {
-        String svc = mServiceName;
-        Log.d(mTag, "-----  Stop the daemon just in case: " + mServiceName);
-        SystemProperties.set(SVC_STOP_CMD, mServiceName);
-        if (!blockUntil(SVC_STATE_STOPPED, 5)) {
-            throw new IOException("cannot start service anew: " + svc
-                    + ", it is still running");
-        }
-
-        Log.d(mTag, "+++++  Start: " + svc);
-        SystemProperties.set(SVC_START_CMD, svc);
-
-        boolean success = blockUntil(SVC_STATE_RUNNING, WAITING_TIME);
-
-        if (success) {
-            Log.d(mTag, "-----  Running: " + svc + ", create keepalive socket");
-            LocalSocket s = mKeepaliveSocket = createServiceSocket();
-            setState(ProcessState.RUNNING);
-
-            if (s == null) {
-                // no socket connection, stop hosting the service
-                stop();
-                return;
-            }
-            try {
-                for (;;) {
-                    InputStream in = s.getInputStream();
-                    int data = in.read();
-                    if (data >= 0) {
-                        Log.d(mTag, "got data from control socket: " + data);
-
-                        setSocketResult(data);
-                    } else {
-                        // service is gone
-                        if (mControlSocketInUse) setSocketResult(-1);
-                        break;
-                    }
-                }
-                Log.d(mTag, "control connection closed");
-            } catch (IOException e) {
-                if (e instanceof VpnConnectingError) {
-                    throw e;
-                } else {
-                    Log.d(mTag, "control socket broken: " + e.getMessage());
-                }
-            }
-
-            // Wait 5 seconds for the service to exit
-            success = blockUntil(SVC_STATE_STOPPED, 5);
-            Log.d(mTag, "stopping " + svc + ", success? " + success);
-        } else {
-            setState(ProcessState.STOPPED);
-            throw new IOException("cannot start service: " + svc);
-        }
-    }
-
-    private LocalSocket createServiceSocket() throws IOException {
-        LocalSocket s = new LocalSocket();
-        LocalSocketAddress a = new LocalSocketAddress(mSocketName,
-                LocalSocketAddress.Namespace.RESERVED);
-
-        // try a few times in case the service has not listen()ed
-        IOException excp = null;
-        for (int i = 0; i < 10; i++) {
-            try {
-                s.connect(a);
-                return s;
-            } catch (IOException e) {
-                Log.d(mTag, "service not yet listen()ing; try again");
-                excp = e;
-                sleep(500);
-            }
-        }
-        throw excp;
-    }
-
-    private OutputStream getControlSocketOutput() throws IOException {
-        if (mKeepaliveSocket != null) {
-            mControlSocketInUse = true;
-            mSocketResult = null;
-            return mKeepaliveSocket.getOutputStream();
-        } else {
-            throw new IOException("no control socket available");
-        }
-    }
-
-    private void checkSocketResult() throws IOException {
-        try {
-            // will be notified when the result comes back from service
-            if (mSocketResult == null) wait();
-        } catch (InterruptedException e) {
-            Log.d(mTag, "checkSocketResult(): " + e);
-        } finally {
-            mControlSocketInUse = false;
-            if ((mSocketResult == null) || (mSocketResult < 0)) {
-                throw new IOException("socket error, result from service: "
-                        + mSocketResult);
-            }
-        }
-    }
-
-    private synchronized void setSocketResult(int result)
-            throws VpnConnectingError {
-        if (mControlSocketInUse) {
-            mSocketResult = result;
-            notifyAll();
-        } else if (result > 0) {
-            // error from daemon
-            throw new VpnConnectingError((result == AUTH_ERROR_CODE)
-                    ? VpnManager.VPN_ERROR_AUTH
-                    : VpnManager.VPN_ERROR_CONNECTION_FAILED);
-        }
-    }
-
-    private void setResultAndCloseControlSocket(int result)
-            throws VpnConnectingError {
-        setSocketResult(result);
-        try {
-            mKeepaliveSocket.shutdownInput();
-            mKeepaliveSocket.shutdownOutput();
-            mKeepaliveSocket.close();
-        } catch (IOException e) {
-            Log.e(mTag, "close keepalive socket", e);
-        } finally {
-            mKeepaliveSocket = null;
-        }
-    }
-
-    /**
-     * Waits for the process to be in the expected state. The method returns
-     * false if after the specified duration (in seconds), the process is still
-     * not in the expected state.
-     */
-    private boolean blockUntil(String expectedState, int waitTime) {
-        String cmd = SVC_STATE_CMD_PREFIX + mServiceName;
-        int sleepTime = 200; // ms
-        int n = waitTime * 1000 / sleepTime;
-        for (int i = 0; i < n; i++) {
-            if (expectedState.equals(SystemProperties.get(cmd))) {
-                Log.d(mTag, mServiceName + " is " + expectedState + " after "
-                        + (i * sleepTime) + " msec");
-                break;
-            }
-            sleep(sleepTime);
-        }
-        return expectedState.equals(SystemProperties.get(cmd));
-    }
-
-    private void outputString(OutputStream out, String s) throws IOException {
-        byte[] bytes = s.getBytes();
-        out.write(bytes.length);
-        out.write(bytes);
-        out.flush();
-    }
-}
diff --git a/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java b/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java
new file mode 100644
index 0000000..b749821
--- /dev/null
+++ b/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2009, 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.vpn;
+
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.net.vpn.VpnManager;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Proxy to start, stop and interact with a VPN daemon.
+ * The daemon is expected to accept connection through Unix domain socket.
+ * When the proxy successfully starts the daemon, it will establish a socket
+ * connection with the daemon, to both send commands to the daemon and receive
+ * response and connecting error code from the daemon.
+ */
+class DaemonProxy {
+    private static final int WAITING_TIME = 15; // sec
+
+    private static final String SVC_STATE_CMD_PREFIX = "init.svc.";
+    private static final String SVC_START_CMD = "ctl.start";
+    private static final String SVC_STOP_CMD = "ctl.stop";
+    private static final String SVC_STATE_RUNNING = "running";
+    private static final String SVC_STATE_STOPPED = "stopped";
+
+    private static final int END_OF_ARGUMENTS = 255;
+
+    private String mName;
+    private LocalSocket mControlSocket;
+    private String mTag;
+
+    /**
+     * Creates a proxy of the specified daemon.
+     * @param daemonName name of the daemon
+     */
+    DaemonProxy(String daemonName) {
+        mName = daemonName;
+        mTag = "SProxy_" + daemonName;
+    }
+
+    String getName() {
+        return mName;
+    }
+
+    void start() throws IOException {
+        String svc = mName;
+        Log.d(mTag, "-----  Stop the daemon just in case: " + mName);
+        SystemProperties.set(SVC_STOP_CMD, mName);
+        if (!blockUntil(SVC_STATE_STOPPED, 5)) {
+            throw new IOException("cannot start service anew: " + svc
+                    + ", it is still running");
+        }
+
+        Log.d(mTag, "+++++  Start: " + svc);
+        SystemProperties.set(SVC_START_CMD, svc);
+
+        if (!blockUntil(SVC_STATE_RUNNING, WAITING_TIME)) {
+            throw new IOException("cannot start service: " + svc);
+        } else {
+            mControlSocket = createServiceSocket();
+        }
+    }
+
+    void sendCommand(String ...args) throws IOException {
+        OutputStream out = getControlSocketOutput();
+        for (String arg : args) outputString(out, arg);
+        out.write(END_OF_ARGUMENTS);
+        out.flush();
+
+        int result = getResultFromSocket(true);
+        if (result != args.length) {
+            throw new IOException("socket error, result from service: "
+                    + result);
+        }
+    }
+
+    // returns 0 if nothing is in the receive buffer
+    int getResultFromSocket() throws IOException {
+        return getResultFromSocket(false);
+    }
+
+    void closeControlSocket() {
+        if (mControlSocket == null) return;
+        try {
+            mControlSocket.close();
+        } catch (IOException e) {
+            Log.e(mTag, "close control socket", e);
+        } finally {
+            mControlSocket = null;
+        }
+    }
+
+    void stop() {
+        String svc = mName;
+        Log.d(mTag, "-----  Stop: " + svc);
+        SystemProperties.set(SVC_STOP_CMD, svc);
+        boolean success = blockUntil(SVC_STATE_STOPPED, 5);
+        Log.d(mTag, "stopping " + svc + ", success? " + success);
+    }
+
+    boolean isStopped() {
+        String cmd = SVC_STATE_CMD_PREFIX + mName;
+        return SVC_STATE_STOPPED.equals(SystemProperties.get(cmd));
+    }
+
+    private int getResultFromSocket(boolean blocking) throws IOException {
+        LocalSocket s = mControlSocket;
+        if (s == null) return 0;
+        InputStream in = s.getInputStream();
+        if (!blocking && in.available() == 0) return 0;
+
+        int data = in.read();
+        Log.d(mTag, "got data from control socket: " + data);
+
+        return data;
+    }
+
+    private LocalSocket createServiceSocket() throws IOException {
+        LocalSocket s = new LocalSocket();
+        LocalSocketAddress a = new LocalSocketAddress(mName,
+                LocalSocketAddress.Namespace.RESERVED);
+
+        // try a few times in case the service has not listen()ed
+        IOException excp = null;
+        for (int i = 0; i < 10; i++) {
+            try {
+                s.connect(a);
+                return s;
+            } catch (IOException e) {
+                Log.d(mTag, "service not yet listen()ing; try again");
+                excp = e;
+                sleep(500);
+            }
+        }
+        throw excp;
+    }
+
+    private OutputStream getControlSocketOutput() throws IOException {
+        if (mControlSocket != null) {
+            return mControlSocket.getOutputStream();
+        } else {
+            throw new IOException("no control socket available");
+        }
+    }
+
+    /**
+     * Waits for the process to be in the expected state. The method returns
+     * false if after the specified duration (in seconds), the process is still
+     * not in the expected state.
+     */
+    private boolean blockUntil(String expectedState, int waitTime) {
+        String cmd = SVC_STATE_CMD_PREFIX + mName;
+        int sleepTime = 200; // ms
+        int n = waitTime * 1000 / sleepTime;
+        for (int i = 0; i < n; i++) {
+            if (expectedState.equals(SystemProperties.get(cmd))) {
+                Log.d(mTag, mName + " is " + expectedState + " after "
+                        + (i * sleepTime) + " msec");
+                break;
+            }
+            sleep(sleepTime);
+        }
+        return expectedState.equals(SystemProperties.get(cmd));
+    }
+
+    private void outputString(OutputStream out, String s) throws IOException {
+        byte[] bytes = s.getBytes();
+        out.write(bytes.length);
+        out.write(bytes);
+        out.flush();
+    }
+
+    private void sleep(int msec) {
+        try {
+            Thread.currentThread().sleep(msec);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
index 7b3ddf8..8efd7c4 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
@@ -25,7 +25,7 @@
  * connection.
  */
 class L2tpIpsecPskService extends VpnService<L2tpIpsecPskProfile> {
-    private static final String IPSEC_DAEMON = "racoon";
+    private static final String IPSEC = "racoon";
 
     @Override
     protected void connect(String serverIp, String username, String password)
@@ -33,9 +33,9 @@
         L2tpIpsecPskProfile p = getProfile();
 
         // IPSEC
-        AndroidServiceProxy ipsecService = startService(IPSEC_DAEMON);
-        ipsecService.sendCommand(serverIp, L2tpService.L2TP_PORT,
-                p.getPresharedKey());
+        DaemonProxy ipsec = startDaemon(IPSEC);
+        ipsec.sendCommand(serverIp, L2tpService.L2TP_PORT, p.getPresharedKey());
+        ipsec.closeControlSocket();
 
         sleep(2000); // 2 seconds
 
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
index e2d4ff4..56694b6 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
@@ -25,15 +25,16 @@
  * The service that manages the certificate based L2TP-over-IPSec VPN connection.
  */
 class L2tpIpsecService extends VpnService<L2tpIpsecProfile> {
-    private static final String IPSEC_DAEMON = "racoon";
+    private static final String IPSEC = "racoon";
 
     @Override
     protected void connect(String serverIp, String username, String password)
             throws IOException {
         // IPSEC
-        AndroidServiceProxy ipsecService = startService(IPSEC_DAEMON);
-        ipsecService.sendCommand(serverIp, L2tpService.L2TP_PORT,
+        DaemonProxy ipsec = startDaemon(IPSEC);
+        ipsec.sendCommand(serverIp, L2tpService.L2TP_PORT,
                 getUserkeyPath(), getUserCertPath(), getCaCertPath());
+        ipsec.closeControlSocket();
 
         sleep(2000); // 2 seconds
 
diff --git a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
index 5fac799..805a5b5 100644
--- a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
+++ b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
@@ -24,7 +24,7 @@
  * A helper class for sending commands to the MTP daemon (mtpd).
  */
 class MtpdHelper {
-    private static final String MTPD_SERVICE = "mtpd";
+    private static final String MTPD = "mtpd";
     private static final String VPN_LINKNAME = "vpn";
     private static final String PPP_ARGS_SEPARATOR = "";
 
@@ -37,7 +37,7 @@
         args.add(PPP_ARGS_SEPARATOR);
         addPppArguments(vpnService, args, serverIp, username, password);
 
-        AndroidServiceProxy mtpd = vpnService.startService(MTPD_SERVICE);
+        DaemonProxy mtpd = vpnService.startDaemon(MTPD);
         mtpd.sendCommand(args.toArray(new String[args.size()]));
     }
 
diff --git a/packages/VpnServices/src/com/android/server/vpn/NormalProcessProxy.java b/packages/VpnServices/src/com/android/server/vpn/NormalProcessProxy.java
deleted file mode 100644
index f0bbc34..0000000
--- a/packages/VpnServices/src/com/android/server/vpn/NormalProcessProxy.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import android.util.Log;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.IOException;
-
-/**
- * Proxy to perform a command with arguments.
- */
-public class NormalProcessProxy extends ProcessProxy {
-    private Process mProcess;
-    private String[] mArgs;
-    private String mTag;
-
-    /**
-     * Creates a proxy with the arguments.
-     * @param args the argument list with the first one being the command
-     */
-    public NormalProcessProxy(String ...args) {
-        if ((args == null) || (args.length == 0)) {
-            throw new IllegalArgumentException();
-        }
-        mArgs = args;
-        mTag = "PProxy_" + getName();
-    }
-
-    @Override
-    public String getName() {
-        return mArgs[0];
-    }
-
-    @Override
-    public synchronized void stop() {
-        if (isStopped()) return;
-        getHostThread().interrupt();
-        // TODO: not sure how to reliably kill a process
-        mProcess.destroy();
-        setState(ProcessState.STOPPING);
-    }
-
-    @Override
-    protected void performTask() throws IOException, InterruptedException {
-        String[] args = mArgs;
-        Log.d(mTag, "+++++  Execute: " + getEntireCommand());
-        ProcessBuilder pb = new ProcessBuilder(args);
-        setState(ProcessState.RUNNING);
-        Process p = mProcess = pb.start();
-        BufferedReader reader = new BufferedReader(new InputStreamReader(
-                p.getInputStream()));
-        while (true) {
-            String line = reader.readLine();
-            if ((line == null) || isStopping()) break;
-            Log.d(mTag, line);
-        }
-
-        Log.d(mTag, "-----  p.waitFor(): " + getName());
-        p.waitFor();
-        Log.d(mTag, "-----  Done: " + getName());
-    }
-
-    private CharSequence getEntireCommand() {
-        String[] args = mArgs;
-        StringBuilder sb = new StringBuilder(args[0]);
-        for (int i = 1; i < args.length; i++) sb.append(' ').append(args[i]);
-        return sb;
-    }
-}
diff --git a/packages/VpnServices/src/com/android/server/vpn/ProcessProxy.java b/packages/VpnServices/src/com/android/server/vpn/ProcessProxy.java
deleted file mode 100644
index 50fbf4b..0000000
--- a/packages/VpnServices/src/com/android/server/vpn/ProcessProxy.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import android.os.ConditionVariable;
-
-import java.io.IOException;
-
-/**
- * A proxy class that spawns a process to accomplish a certain task.
- */
-public abstract class ProcessProxy {
-    /**
-     * Defines the interface to call back when the process is finished or an
-     * error occurs during execution.
-     */
-    public static interface Callback {
-        /**
-         * Called when the process is finished.
-         * @param proxy the proxy that hosts the process
-         */
-        void done(ProcessProxy proxy);
-
-        /**
-         * Called when some error occurs.
-         * @param proxy the proxy that hosts the process
-         */
-        void error(ProcessProxy proxy, Throwable error);
-    }
-
-    protected enum ProcessState {
-        STOPPED, STARTING, RUNNING, STOPPING, ERROR
-    }
-
-    private ProcessState mState = ProcessState.STOPPED;
-    private ConditionVariable mLock = new ConditionVariable();
-    private Thread mThread;
-
-    /**
-     * Returns the name of the process.
-     */
-    public abstract String getName();
-
-    /**
-     * Starts the process with a callback.
-     * @param callback the callback to get notified when the process is finished
-     *      or an error occurs during execution
-     * @throws IOException when the process is already running or failed to
-     *      start
-     */
-    public synchronized void start(final Callback callback) throws IOException {
-        if (!isStopped()) {
-            throw new IOException("Process is already running: " + this);
-        }
-        mLock.close();
-        setState(ProcessState.STARTING);
-        Thread thread = new Thread(new Runnable() {
-            public void run() {
-                try {
-                    performTask();
-                    setState(ProcessState.STOPPED);
-                    mLock.open();
-                    if (callback != null) callback.done(ProcessProxy.this);
-                } catch (Throwable e) {
-                    setState(ProcessState.ERROR);
-                    if (callback != null) callback.error(ProcessProxy.this, e);
-                } finally {
-                    mThread = null;
-                }
-            }
-        });
-        thread.setPriority(Thread.MIN_PRIORITY);
-        thread.start();
-        mThread = thread;
-        if (!waitUntilRunning()) {
-            throw new IOException("Failed to start the process: " + this);
-        }
-    }
-
-    /**
-     * Starts the process.
-     * @throws IOException when the process is already running or failed to
-     *      start
-     */
-    public synchronized void start() throws IOException {
-        start(null);
-        if (!waitUntilDone()) {
-            throw new IOException("Failed to complete the process: " + this);
-        }
-    }
-
-    /**
-     * Returns the thread that hosts the process.
-     */
-    public Thread getHostThread() {
-        return mThread;
-    }
-
-    /**
-     * Blocks the current thread until the hosted process is finished.
-     *
-     * @return true if the process is finished normally; false if an error
-     *      occurs
-     */
-    public boolean waitUntilDone() {
-        while (!mLock.block(1000)) {
-            if (isStopped() || isInError()) break;
-        }
-        return isStopped();
-    }
-
-    /**
-     * Blocks the current thread until the hosted process is running.
-     *
-     * @return true if the process is running normally; false if the process
-     *      is in another state
-     */
-    private boolean waitUntilRunning() {
-        for (;;) {
-            if (!isStarting()) break;
-        }
-        return isRunning();
-    }
-
-    /**
-     * Stops and destroys the process.
-     */
-    public abstract void stop();
-
-    /**
-     * Checks whether the process is finished.
-     * @return true if the process is stopped
-     */
-    public boolean isStopped() {
-        return (mState == ProcessState.STOPPED);
-    }
-
-    /**
-     * Checks whether the process is being stopped.
-     * @return true if the process is being stopped
-     */
-    public boolean isStopping() {
-        return (mState == ProcessState.STOPPING);
-    }
-
-    /**
-     * Checks whether the process is being started.
-     * @return true if the process is being started
-     */
-    public boolean isStarting() {
-        return (mState == ProcessState.STARTING);
-    }
-
-    /**
-     * Checks whether the process is running.
-     * @return true if the process is running
-     */
-    public boolean isRunning() {
-        return (mState == ProcessState.RUNNING);
-    }
-
-    /**
-     * Checks whether some error has occurred and the process is stopped.
-     * @return true if some error has occurred and the process is stopped
-     */
-    public boolean isInError() {
-        return (mState == ProcessState.ERROR);
-    }
-
-    /**
-     * Performs the actual task. Subclasses must make sure that the method
-     * is blocked until the task is done or an error occurs.
-     */
-    protected abstract void performTask()
-            throws IOException, InterruptedException;
-
-    /**
-     * Sets the process state.
-     * @param state the new state to be in
-     */
-    protected void setState(ProcessState state) {
-        mState = state;
-    }
-
-    /**
-     * Makes the current thread sleep for the specified time.
-     * @param msec time to sleep in miliseconds
-     */
-    protected void sleep(int msec) {
-        try {
-            Thread.currentThread().sleep(msec);
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
-        }
-    }
-}
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index 87bd780..60a07d5 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -50,14 +50,15 @@
     private static final String REMOTE_IP = "net.ipremote";
     private static final String DNS_DOMAIN_SUFFICES = "net.dns.search";
 
+    private static final int AUTH_ERROR_CODE = 51;
+
     private final String TAG = VpnService.class.getSimpleName();
 
     E mProfile;
     VpnServiceBinder mContext;
 
     private VpnState mState = VpnState.IDLE;
-    private boolean mInError;
-    private VpnConnectingError mError;
+    private Throwable mError;
 
     // connection settings
     private String mOriginalDns1;
@@ -68,8 +69,8 @@
 
     private long mStartTime; // VPN connection start time
 
-    // for helping managing multiple Android services
-    private ServiceHelper mServiceHelper = new ServiceHelper();
+    // for helping managing multiple daemons
+    private DaemonHelper mDaemonHelper = new DaemonHelper();
 
     // for helping showing, updating notification
     private NotificationHelper mNotification = new NotificationHelper();
@@ -81,18 +82,11 @@
             String password) throws IOException;
 
     /**
-     * Tears down the VPN connection. The base class simply terminates all the
-     * Android services. A subclass may need to do some clean-up before that.
+     * Starts a VPN daemon.
      */
-    protected void disconnect() {
-    }
-
-    /**
-     * Starts an Android service defined in init.rc.
-     */
-    protected AndroidServiceProxy startService(String serviceName)
+    protected DaemonProxy startDaemon(String daemonName)
             throws IOException {
-        return mServiceHelper.startService(serviceName);
+        return mDaemonHelper.startDaemon(daemonName);
     }
 
     /**
@@ -109,28 +103,6 @@
         return InetAddress.getByName(hostName).getHostAddress();
     }
 
-    /**
-     * Sets the system property. The method is blocked until the value is
-     * settled in.
-     * @param name the name of the property
-     * @param value the value of the property
-     * @throws IOException if it fails to set the property within 2 seconds
-     */
-    protected void setSystemProperty(String name, String value)
-            throws IOException {
-        SystemProperties.set(name, value);
-        for (int i = 0; i < 5; i++) {
-            String v = SystemProperties.get(name);
-            if (v.equals(value)) {
-                return;
-            } else {
-                Log.d(TAG, "sys_prop: wait for " + name + " to settle in");
-                sleep(400);
-            }
-        }
-        throw new IOException("Failed to set system property: " + name);
-    }
-
     void setContext(VpnServiceBinder context, E profile) {
         mContext = context;
         mProfile = profile;
@@ -153,44 +125,42 @@
             return true;
         } catch (Throwable e) {
             Log.e(TAG, "onConnect()", e);
-            mError = newConnectingError(e);
-            onError();
+            onError(e);
             return false;
         }
     }
 
-    synchronized void onDisconnect(boolean cleanUpServices) {
+    synchronized void onDisconnect() {
         try {
             Log.d(TAG, "       disconnecting VPN...");
             mState = VpnState.DISCONNECTING;
             broadcastConnectivity(VpnState.DISCONNECTING);
             mNotification.showDisconnect();
 
-            // subclass implementation
-            if (cleanUpServices) disconnect();
-
-            mServiceHelper.stop();
+            mDaemonHelper.stopAll();
         } catch (Throwable e) {
             Log.e(TAG, "onDisconnect()", e);
+        } finally {
             onFinalCleanUp();
         }
     }
 
-    synchronized void onError() {
+    private void onError(Throwable error) {
         // error may occur during or after connection setup
         // and it may be due to one or all services gone
-        mInError = true;
-        switch (mState) {
-        case CONNECTED:
-            onDisconnect(true);
-            break;
-
-        case CONNECTING:
-            onDisconnect(false);
-            break;
+        if (mError != null) {
+            Log.w(TAG, "   multiple errors occur, record the last one: "
+                    + error);
         }
+        mError = error;
+        onDisconnect();
     }
 
+    private void onError(int errorCode) {
+        onError(new VpnConnectingError(errorCode));
+    }
+
+
     private void onBeforeConnect() {
         mNotification.disableNotification();
 
@@ -201,41 +171,39 @@
     }
 
     private void waitUntilConnectedOrTimedout() {
-        // Run this in the background thread to not block UI
-        new Thread(new Runnable() {
-            public void run() {
-                sleep(2000); // 2 seconds
-                for (int i = 0; i < 60; i++) {
-                    if (VPN_IS_UP.equals(SystemProperties.get(VPN_STATUS))) {
-                        onConnected();
-                        return;
-                    } else if (mState != VpnState.CONNECTING) {
-                        break;
-                    }
-                    sleep(500); // 0.5 second
-                }
-
-                synchronized (VpnService.this) {
-                    if (mState == VpnState.CONNECTING) {
-                        Log.d(TAG, "       connecting timed out !!");
-                        mError = newConnectingError(
-                                new IOException("Connecting timed out"));
-                        onError();
-                    }
-                }
+        sleep(2000); // 2 seconds
+        for (int i = 0; i < 60; i++) {
+            if (mState != VpnState.CONNECTING) {
+                break;
+            } else if (VPN_IS_UP.equals(
+                    SystemProperties.get(VPN_STATUS))) {
+                onConnected();
+                return;
+            } else if (mDaemonHelper.anySocketError()) {
+                return;
             }
-        }).start();
+            sleep(500); // 0.5 second
+        }
+
+        synchronized (VpnService.this) {
+            if (mState == VpnState.CONNECTING) {
+                Log.d(TAG, "       connecting timed out !!");
+                onError(new IOException("Connecting timed out"));
+            }
+        }
     }
 
     private synchronized void onConnected() {
         Log.d(TAG, "onConnected()");
 
+        mDaemonHelper.closeSockets();
         saveVpnDnsProperties();
         saveAndSetDomainSuffices();
-        startConnectivityMonitor();
 
         mState = VpnState.CONNECTED;
         broadcastConnectivity(VpnState.CONNECTED);
+
+        enterConnectivityLoop();
     }
 
     private synchronized void onFinalCleanUp() {
@@ -244,7 +212,7 @@
         if (mState == VpnState.IDLE) return;
 
         // keep the notification when error occurs
-        if (!mInError) mNotification.disableNotification();
+        if (!anyError()) mNotification.disableNotification();
 
         restoreOriginalDnsProperties();
         restoreOriginalDomainSuffices();
@@ -255,37 +223,8 @@
         mContext.stopSelf();
     }
 
-    private VpnConnectingError newConnectingError(Throwable e) {
-        return new VpnConnectingError(
-                (e instanceof UnknownHostException)
-                ? VpnManager.VPN_ERROR_UNKNOWN_SERVER
-                : VpnManager.VPN_ERROR_CONNECTION_FAILED);
-    }
-
-    private synchronized void onOneServiceGone() {
-        switch (mState) {
-        case IDLE:
-        case DISCONNECTING:
-            break;
-
-        default:
-            onError();
-        }
-    }
-
-    private synchronized void onAllServicesGone() {
-        switch (mState) {
-        case IDLE:
-            break;
-
-        case DISCONNECTING:
-            // daemons are gone; now clean up everything
-            onFinalCleanUp();
-            break;
-
-        default:
-            onError();
-        }
+    private boolean anyError() {
+        return (mError != null);
     }
 
     private void restoreOriginalDnsProperties() {
@@ -341,46 +280,65 @@
 
     private void broadcastConnectivity(VpnState s) {
         VpnManager m = new VpnManager(mContext);
-        if ((s == VpnState.IDLE) && (mError != null)) {
-            m.broadcastConnectivity(mProfile.getName(), s,
-                    mError.getErrorCode());
+        Throwable err = mError;
+        if ((s == VpnState.IDLE) && (err != null)) {
+            if (err instanceof UnknownHostException) {
+                m.broadcastConnectivity(mProfile.getName(), s,
+                        VpnManager.VPN_ERROR_UNKNOWN_SERVER);
+            } else if (err instanceof VpnConnectingError) {
+                m.broadcastConnectivity(mProfile.getName(), s,
+                        ((VpnConnectingError) err).getErrorCode());
+            } else {
+                m.broadcastConnectivity(mProfile.getName(), s,
+                        VpnManager.VPN_ERROR_CONNECTION_FAILED);
+            }
         } else {
             m.broadcastConnectivity(mProfile.getName(), s);
         }
     }
 
-    private void startConnectivityMonitor() {
+    private void enterConnectivityLoop() {
         mStartTime = System.currentTimeMillis();
 
-        new Thread(new Runnable() {
-            public void run() {
-                Log.d(TAG, "   +++++   connectivity monitor running");
-                try {
-                    for (;;) {
-                        synchronized (VpnService.this) {
-                            if (mState != VpnState.CONNECTED) break;
-                            mNotification.update();
-                            checkConnectivity();
-                            VpnService.this.wait(1000); // 1 second
-                        }
-                    }
-                } catch (InterruptedException e) {
-                    Log.e(TAG, "connectivity monitor", e);
+        Log.d(TAG, "   +++++   connectivity monitor running");
+        try {
+            for (;;) {
+                synchronized (VpnService.this) {
+                    if (mState != VpnState.CONNECTED) break;
+                    mNotification.update();
+                    checkConnectivity();
+                    VpnService.this.wait(1000); // 1 second
                 }
-                Log.d(TAG, "   -----   connectivity monitor stopped");
             }
-        }).start();
+        } catch (InterruptedException e) {
+            Log.e(TAG, "connectivity monitor", e);
+        }
+        Log.d(TAG, "   -----   connectivity monitor stopped");
     }
 
     private void checkConnectivity() {
-        checkDnsProperties();
+        if (mDaemonHelper.anyDaemonStopped() || isLocalIpChanged()) {
+            onDisconnect();
+        }
     }
 
-    private void checkDnsProperties() {
+    private boolean isLocalIpChanged() {
+        // TODO
+        if (!isDnsIntact()) {
+            Log.w(TAG, "       local IP changed");
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private boolean isDnsIntact() {
         String dns1 = SystemProperties.get(DNS1);
         if (!mVpnDns1.equals(dns1)) {
             Log.w(TAG, "   dns being overridden by: " + dns1);
-            onError();
+            return false;
+        } else {
+            return true;
         }
     }
 
@@ -391,56 +349,64 @@
         }
     }
 
-    private InetAddress toInetAddress(int addr) throws IOException {
-        byte[] aa = new byte[4];
-        for (int i= 0; i < aa.length; i++) {
-            aa[i] = (byte) (addr & 0x0FF);
-            addr >>= 8;
-        }
-        return InetAddress.getByAddress(aa);
-    }
+    private class DaemonHelper {
+        private List<DaemonProxy> mDaemonList =
+                new ArrayList<DaemonProxy>();
 
-    private class ServiceHelper implements ProcessProxy.Callback {
-        private List<AndroidServiceProxy> mServiceList =
-                new ArrayList<AndroidServiceProxy>();
-
-        // starts an Android service
-        AndroidServiceProxy startService(String serviceName)
+        synchronized DaemonProxy startDaemon(String daemonName)
                 throws IOException {
-            AndroidServiceProxy service = new AndroidServiceProxy(serviceName);
-            mServiceList.add(service);
-            service.start(this);
-            return service;
+            DaemonProxy daemon = new DaemonProxy(daemonName);
+            mDaemonList.add(daemon);
+            daemon.start();
+            return daemon;
         }
 
-        // stops all the Android services
-        void stop() {
-            if (mServiceList.isEmpty()) {
+        synchronized void stopAll() {
+            if (mDaemonList.isEmpty()) {
                 onFinalCleanUp();
             } else {
-                for (AndroidServiceProxy s : mServiceList) s.stop();
+                for (DaemonProxy s : mDaemonList) s.stop();
             }
         }
 
-        //@Override
-        public void done(ProcessProxy p) {
-            Log.d(TAG, "service done: " + p.getName());
-            commonCallback((AndroidServiceProxy) p);
+        synchronized void closeSockets() {
+            for (DaemonProxy s : mDaemonList) s.closeControlSocket();
         }
 
-        //@Override
-        public void error(ProcessProxy p, Throwable e) {
-            Log.e(TAG, "service error: " + p.getName(), e);
-            if (e instanceof VpnConnectingError) {
-                mError = (VpnConnectingError) e;
+        synchronized boolean anyDaemonStopped() {
+            for (DaemonProxy s : mDaemonList) {
+                if (s.isStopped()) {
+                    Log.w(TAG, "       daemon gone: " + s.getName());
+                    return true;
+                }
             }
-            commonCallback((AndroidServiceProxy) p);
+            return false;
         }
 
-        private void commonCallback(AndroidServiceProxy service) {
-            mServiceList.remove(service);
-            onOneServiceGone();
-            if (mServiceList.isEmpty()) onAllServicesGone();
+        private int getResultFromSocket(DaemonProxy s) {
+            try {
+                return s.getResultFromSocket();
+            } catch (IOException e) {
+                return -1;
+            }
+        }
+
+        synchronized boolean anySocketError() {
+            for (DaemonProxy s : mDaemonList) {
+                switch (getResultFromSocket(s)) {
+                    case 0:
+                        continue;
+
+                    case AUTH_ERROR_CODE:
+                        onError(VpnManager.VPN_ERROR_AUTH);
+                        return true;
+
+                    default:
+                        onError(VpnManager.VPN_ERROR_CONNECTION_FAILED);
+                        return true;
+                }
+            }
+            return false;
         }
     }
 
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
index 32b8e51..513a2c9 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
@@ -42,11 +42,13 @@
 
     private final IBinder mBinder = new IVpnService.Stub() {
         public boolean connect(VpnProfile p, String username, String password) {
+            android.util.Log.d("VpnServiceBinder", "becoming foreground");
+            setForeground(true);
             return VpnServiceBinder.this.connect(p, username, password);
         }
 
         public void disconnect() {
-            if (mService != null) mService.onDisconnect(true);
+            VpnServiceBinder.this.disconnect();
         }
 
         public void checkStatus(VpnProfile p) {
@@ -54,21 +56,39 @@
         }
     };
 
-    public void onStart (Intent intent, int startId) {
+    @Override
+    public void onStart(Intent intent, int startId) {
         super.onStart(intent, startId);
-        setForeground(true);
-        android.util.Log.d("VpnServiceBinder", "becomes a foreground service");
     }
 
+    @Override
     public IBinder onBind(Intent intent) {
         return mBinder;
     }
 
-    private synchronized boolean connect(
-            VpnProfile p, String username, String password) {
+    private synchronized boolean connect(final VpnProfile p,
+            final String username, final String password) {
         if (mService != null) return false;
-        mService = createService(p);
-        return mService.onConnect(username, password);
+
+        new Thread(new Runnable() {
+            public void run() {
+                mService = createService(p);
+                mService.onConnect(username, password);
+            }
+        }).start();
+        return true;
+    }
+
+    private synchronized void disconnect() {
+        if (mService == null) return;
+
+        new Thread(new Runnable() {
+            public void run() {
+                mService.onDisconnect();
+                android.util.Log.d("VpnServiceBinder", "becoming background");
+                setForeground(false);
+            }
+        }).start();
     }
 
     private synchronized void checkStatus(VpnProfile p) {
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index c205fc0..63c9eaa 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -368,6 +368,9 @@
      * @param event The event.
      */
     private void tryRecycleLocked(AccessibilityEvent event) {
+        if (event == null) {
+            return;
+        }
         int eventType = event.getEventType();
         List<Service> services = mServices;
 
@@ -378,7 +381,6 @@
                 return;
             }
         }
-
         event.recycle();
     }
 
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index fc1ec03..e74b37b 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -1281,6 +1281,8 @@
                 // again in this case before propagating the exception
                 Log.e(TAG, "Error restoring data for " + packageName, e);
                 clearApplicationDataSynchronous(packageName);
+            } finally {
+                backupDataName.delete();
             }
         }
     }
@@ -1440,7 +1442,7 @@
     // Run a backup pass immediately for any applications that have declared
     // that they have pending updates.
     public void backupNow() throws RemoteException {
-        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "backupNow");
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "backupNow");
 
         if (DEBUG) Log.v(TAG, "Scheduling immediate backup pass");
         synchronized (mQueueLock) {
@@ -1509,13 +1511,13 @@
 
     // Report whether the backup mechanism is currently enabled
     public boolean isBackupEnabled() {
-        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "isBackupEnabled");
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "isBackupEnabled");
         return mEnabled;    // no need to synchronize just to read it
     }
 
     // Report the name of the currently active transport
     public String getCurrentTransport() {
-        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                 "getCurrentTransport");
         Log.v(TAG, "... getCurrentTransport() returning " + mCurrentTransport);
         return mCurrentTransport;
@@ -1544,7 +1546,7 @@
     // name is not one of the available transports, no action is taken and the method
     // returns null.
     public String selectBackupTransport(String transport) {
-        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "selectBackupTransport");
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "selectBackupTransport");
 
         synchronized (mTransports) {
             String prevTransport = null;
@@ -1598,7 +1600,7 @@
 
     // Hand off a restore session
     public IRestoreSession beginRestoreSession(String transport) {
-        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "beginRestoreSession");
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "beginRestoreSession");
 
         synchronized(this) {
             if (mActiveRestoreSession != null) {
@@ -1624,7 +1626,7 @@
 
         // --- Binder interface ---
         public RestoreSet[] getAvailableRestoreSets() throws android.os.RemoteException {
-            mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                     "getAvailableRestoreSets");
 
             try {
@@ -1645,7 +1647,7 @@
 
         public int performRestore(long token, IRestoreObserver observer)
                 throws android.os.RemoteException {
-            mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "performRestore");
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "performRestore");
 
             Log.d(TAG, "performRestore token=" + token + " observer=" + observer);
 
@@ -1666,7 +1668,7 @@
         }
 
         public void endRestoreSession() throws android.os.RemoteException {
-            mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                     "endRestoreSession");
 
             Log.d(TAG, "endRestoreSession");
diff --git a/services/java/com/android/server/HeadsetObserver.java b/services/java/com/android/server/HeadsetObserver.java
index 9b0a2d4..bee3108 100644
--- a/services/java/com/android/server/HeadsetObserver.java
+++ b/services/java/com/android/server/HeadsetObserver.java
@@ -41,10 +41,16 @@
     private static final String HEADSET_STATE_PATH = "/sys/class/switch/h2w/state";
     private static final String HEADSET_NAME_PATH = "/sys/class/switch/h2w/name";
 
+    private static final int BIT_HEADSET = (1 << 0);
+    private static final int BIT_HEADSET_NO_MIC = (1 << 1);
+    private static final int BIT_TTY = (1 << 2);
+    private static final int BIT_FM_HEADSET = (1 << 3);
+    private static final int BIT_FM_SPEAKER = (1 << 4);
+
     private int mHeadsetState;
+    private int mPrevHeadsetState;
     private String mHeadsetName;
-    private boolean mAudioRouteNeedsUpdate;
-    private AudioManager mAudioManager;
+    private boolean mPendingIntent;
 
     private final Context mContext;
     private final WakeLock mWakeLock;  // held while there is a pending route change
@@ -76,6 +82,7 @@
 
         String newName = mHeadsetName;
         int newState = mHeadsetState;
+        mPrevHeadsetState = mHeadsetState;
         try {
             FileReader file = new FileReader(HEADSET_STATE_PATH);
             int len = file.read(buffer, 0, 1024);
@@ -91,20 +98,25 @@
             Log.e(TAG, "" , e);
         }
 
-        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         update(newName, newState);
     }
 
     private synchronized final void update(String newName, int newState) {
         if (newName != mHeadsetName || newState != mHeadsetState) {
-            boolean isUnplug = (newState == 0 && mHeadsetState == 1);
+            boolean isUnplug = false;
+            if ( (mHeadsetState & BIT_HEADSET) > 0 || (mHeadsetState & BIT_HEADSET_NO_MIC) > 0) {
+                if ((newState & BIT_HEADSET) == 0 && (newState & BIT_HEADSET_NO_MIC) == 0)
+                    isUnplug = true;
+            }
             mHeadsetName = newName;
+            mPrevHeadsetState = mHeadsetState;
             mHeadsetState = newState;
-            mAudioRouteNeedsUpdate = true;
-
-            sendIntent(isUnplug);
+            mPendingIntent = true;
 
             if (isUnplug) {
+                Intent intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
+                mContext.sendBroadcast(intent);
+
                 // It can take hundreds of ms flush the audio pipeline after
                 // apps pause audio playback, but audio route changes are
                 // immediate, so delay the route change by 1000ms.
@@ -113,12 +125,13 @@
                 mWakeLock.acquire();
                 mHandler.sendEmptyMessageDelayed(0, 1000);
             } else {
-                updateAudioRoute();
+                sendIntent();
+                mPendingIntent = false;
             }
         }
     }
 
-    private synchronized final void sendIntent(boolean isUnplug) {
+    private synchronized final void sendIntent() {
         //  Pack up the values and broadcast them to everyone
         Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -128,24 +141,15 @@
 
         // TODO: Should we require a permission?
         ActivityManagerNative.broadcastStickyIntent(intent, null);
-
-        if (isUnplug) {
-            intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
-            mContext.sendBroadcast(intent);
-        }
-    }
-
-    private synchronized final void updateAudioRoute() {
-        if (mAudioRouteNeedsUpdate) {
-            mAudioManager.setWiredHeadsetOn(mHeadsetState == 1);
-            mAudioRouteNeedsUpdate = false;
-        }
     }
 
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            updateAudioRoute();
+            if (mPendingIntent) {
+                sendIntent();
+                mPendingIntent = false;
+            }
             mWakeLock.release();
         }
     };
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 3e98132..0ac5740 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -213,7 +213,7 @@
             
             // We only consider the first pointer when computing the edge
             // flags, since they are global to the event.
-            if (action != MotionEvent.ACTION_DOWN) {
+            if (action == MotionEvent.ACTION_DOWN) {
                 if (scaled[MotionEvent.SAMPLE_X] <= 0) {
                     edgeFlags |= MotionEvent.EDGE_LEFT;
                 } else if (scaled[MotionEvent.SAMPLE_X] >= dispW) {
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index 17e9625..e0ee7ed 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -35,7 +35,6 @@
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -55,6 +54,7 @@
 
     final SparseArray<InputDevice> mDevices = new SparseArray<InputDevice>();
     final ArrayList<VirtualKey> mVirtualKeys = new ArrayList<VirtualKey>();
+    final HapticFeedbackCallback mHapticFeedbackCallback;
     
     int mGlobalMetaState = 0;
     boolean mHaveGlobalMetaState = false;
@@ -107,6 +107,10 @@
         int filterEvent(QueuedEvent ev);
     }
     
+    public interface HapticFeedbackCallback {
+        void virtualKeyFeedback(KeyEvent event);
+    }
+    
     static class QueuedEvent {
         InputDevice inputDevice;
         long whenNano;
@@ -264,11 +268,13 @@
         }
     }
 
-    KeyInputQueue(Context context) {
+    KeyInputQueue(Context context, HapticFeedbackCallback  hapticFeedbackCallback) {
         if (MEASURE_LATENCY) {
             lt = new LatencyTimer(100, 1000);
         }
 
+        mHapticFeedbackCallback = hapticFeedbackCallback;
+        
         readVirtualKeys();
         readExcludedDevices();
         
@@ -539,14 +545,40 @@
                                             ms.mLastDown[0] = ms.mDown[0];
                                             if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
                                                     "Generate key up for: " + vk.scancode);
+                                            KeyEvent event = newKeyEvent(di,
+                                                    di.mKeyDownTime, curTime, false,
+                                                    vk.lastKeycode,
+                                                    0, vk.scancode,
+                                                    KeyEvent.FLAG_VIRTUAL_HARD_KEY);
+                                            mHapticFeedbackCallback.virtualKeyFeedback(event);
                                             addLocked(di, curTimeNano, ev.flags,
                                                     RawInputEvent.CLASS_KEYBOARD,
-                                                    newKeyEvent(di, di.mKeyDownTime,
-                                                            curTime, false,
-                                                            vk.lastKeycode,
-                                                            0, vk.scancode, 0));
+                                                    event);
+                                        } else if (isInsideDisplay(di)) {
+                                            // Whoops the pointer has moved into
+                                            // the display area!  Cancel the
+                                            // virtual key and start a pointer
+                                            // motion.
+                                            mPressedVirtualKey = null;
+                                            if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
+                                                    "Cancel key up for: " + vk.scancode);
+                                            KeyEvent event = newKeyEvent(di,
+                                                    di.mKeyDownTime, curTime, false,
+                                                    vk.lastKeycode,
+                                                    0, vk.scancode,
+                                                    KeyEvent.FLAG_CANCELED |
+                                                    KeyEvent.FLAG_VIRTUAL_HARD_KEY);
+                                            mHapticFeedbackCallback.virtualKeyFeedback(event);
+                                            addLocked(di, curTimeNano, ev.flags,
+                                                    RawInputEvent.CLASS_KEYBOARD,
+                                                    event);
+                                            doMotion = true;
+                                            for (int i=InputDevice.MAX_POINTERS-1; i>=0; i--) {
+                                                ms.mLastDown[i] = false;
+                                            }
                                         }
-                                    } else if (ms.mDown[0] && !ms.mLastDown[0]) {
+                                    }
+                                    if (doMotion && ms.mDown[0] && !ms.mLastDown[0]) {
                                         vk = findSoftButton(di);
                                         if (vk != null) {
                                             doMotion = false;
@@ -558,12 +590,15 @@
                                             if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
                                                     "Generate key down for: " + vk.scancode
                                                     + " (keycode=" + vk.lastKeycode + ")");
+                                            KeyEvent event = newKeyEvent(di,
+                                                    di.mKeyDownTime, curTime, true,
+                                                    vk.lastKeycode, 0,
+                                                    vk.scancode,
+                                                    KeyEvent.FLAG_VIRTUAL_HARD_KEY);
+                                            mHapticFeedbackCallback.virtualKeyFeedback(event);
                                             addLocked(di, curTimeNano, ev.flags,
                                                     RawInputEvent.CLASS_KEYBOARD,
-                                                    newKeyEvent(di, di.mKeyDownTime,
-                                                            curTime, true,
-                                                            vk.lastKeycode, 0,
-                                                            vk.scancode, 0));
+                                                    event);
                                         }
                                     }
                                     
@@ -618,17 +653,12 @@
         }
     };
 
-    private VirtualKey findSoftButton(InputDevice dev) {
-        final int N = mVirtualKeys.size();
-        if (N <= 0) {
-            return null;
-        }
-        
+    private boolean isInsideDisplay(InputDevice dev) {
         final InputDevice.AbsoluteInfo absx = dev.absX;
         final InputDevice.AbsoluteInfo absy = dev.absY;
         final InputDevice.MotionState absm = dev.mAbs;
         if (absx == null || absy == null || absm == null) {
-            return null;
+            return true;
         }
         
         if (absm.mCurData[MotionEvent.SAMPLE_X] >= absx.minValue
@@ -639,9 +669,23 @@
                     + absm.mCurData[MotionEvent.SAMPLE_X]
                     + "," + absm.mCurData[MotionEvent.SAMPLE_Y]
                     + ") inside of display");
+            return true;
+        }
+        
+        return false;
+    }
+    
+    private VirtualKey findSoftButton(InputDevice dev) {
+        final int N = mVirtualKeys.size();
+        if (N <= 0) {
             return null;
         }
         
+        if (isInsideDisplay(dev)) {
+            return null;
+        }
+        
+        final InputDevice.MotionState absm = dev.mAbs;
         for (int i=0; i<N; i++) {
             VirtualKey sb = mVirtualKeys.get(i);
             sb.computeHitRect(dev, mDisplayWidth, mDisplayHeight);
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 38fb7c9..aac7124 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -90,7 +90,7 @@
     private NotificationRecord mSoundNotification;
     private AsyncPlayer mSound;
     private boolean mSystemReady;
-    private int mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
+    private int mDisabledNotifications;
 
     private NotificationRecord mVibrateNotification;
     private Vibrator mVibrator = new Vibrator();
@@ -368,6 +368,15 @@
         mStatusBarService = statusBar;
         statusBar.setNotificationCallbacks(mNotificationCallbacks);
 
+        // Don't start allowing notifications until the setup wizard has run once.
+        // After that, including subsequent boots, init with notifications turned on.
+        // This works on the first boot because the setup wizard will toggle this
+        // flag at least once and we'll go back to 0 after that.
+        if (0 == Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.DEVICE_PROVISIONED, 0)) {
+            mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
+        }
+
         // register for battery changed notifications
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
@@ -1049,6 +1058,8 @@
             pw.println("  mSoundNotification=" + mSoundNotification);
             pw.println("  mSound=" + mSound);
             pw.println("  mVibrateNotification=" + mVibrateNotification);
+            pw.println("  mDisabledNotifications=0x" + Integer.toHexString(mDisabledNotifications));
+            pw.println("  mSystemReady=" + mSystemReady);
         }
     }
 }
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 9c60157..d6cd4ef 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4905,26 +4905,40 @@
                     if (ps.pkg != null) {
                         pw.print("    dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
                         pw.print("    targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
-                        pw.print("    densities="); pw.println(ps.pkg.supportsDensityList);
-                        ArrayList<String> screens = new ArrayList<String>();
+                        pw.print("    supportsScreens=[");
+                        boolean first = true;
                         if ((ps.pkg.applicationInfo.flags & 
                                 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
-                            screens.add("medium");
+                            if (!first) pw.print(", ");
+                            first = false;
+                            pw.print("medium");
                         }
                         if ((ps.pkg.applicationInfo.flags & 
                                 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
-                            screens.add("large");
+                            if (!first) pw.print(", ");
+                            first = false;
+                            pw.print("large");
                         }
                         if ((ps.pkg.applicationInfo.flags & 
                                 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
-                            screens.add("small,");
+                            if (!first) pw.print(", ");
+                            first = false;
+                            pw.print("small");
                         }
                         if ((ps.pkg.applicationInfo.flags & 
                                 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
-                            screens.add("resizeable,");
+                            if (!first) pw.print(", ");
+                            first = false;
+                            pw.print("resizeable");
                         }
-                        pw.print("    supportsScreens="); pw.println(screens);
+                        if ((ps.pkg.applicationInfo.flags & 
+                                ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
+                            if (!first) pw.print(", ");
+                            first = false;
+                            pw.print("anyDensity");
+                        }
                     }
+                    pw.println("]");
                     pw.print("    timeStamp="); pw.println(ps.getTimeStampStr());
                     pw.print("    signatures="); pw.println(ps.signatures);
                     pw.print("    permissionsFixed="); pw.print(ps.permissionsFixed);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 67e8cf3..f25c221 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -888,6 +888,17 @@
                 break setVariables;
             }
 
+            if ((config.phase2 != null) && !WifiNative.setNetworkVariableCommand(
+                    netId,
+                    WifiConfiguration.phase2VarName,
+                    config.phase2)) {
+                if (DBG) {
+                    Log.d(TAG, config.SSID + ": failed to set phase2: "+
+                          config.phase2);
+                }
+                break setVariables;
+            }
+
             if ((config.identity != null) && !WifiNative.setNetworkVariableCommand(
                     netId,
                     WifiConfiguration.identityVarName,
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index b43acaf..78ca831 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -125,7 +125,8 @@
 import java.util.List;
 
 /** {@hide} */
-public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor {
+public class WindowManagerService extends IWindowManager.Stub
+        implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
     static final String TAG = "WindowManager";
     static final boolean DEBUG = false;
     static final boolean DEBUG_FOCUS = false;
@@ -4686,7 +4687,8 @@
                                     callingPid, callingUid)
                                     == PackageManager.PERMISSION_GRANTED) {
                         mPolicy.interceptKeyTi(null, keycode,
-                                nextKey.getMetaState(), down, repeatCount);
+                                nextKey.getMetaState(), down, repeatCount,
+                                nextKey.getFlags());
                     }
                     Log.w(TAG, "Event timeout during app switch: dropping "
                             + nextKey);
@@ -4709,7 +4711,8 @@
                                 callingPid, callingUid)
                                 == PackageManager.PERMISSION_GRANTED) {
                     if (mPolicy.interceptKeyTi(focus,
-                            keycode, nextKey.getMetaState(), down, repeatCount)) {
+                            keycode, nextKey.getMetaState(), down, repeatCount, 
+                            nextKey.getFlags())) {
                         return CONSUMED_EVENT_TOKEN;
                     }
                 }
@@ -5129,7 +5132,7 @@
         PowerManager.WakeLock mHoldingScreen;
 
         KeyQ() {
-            super(mContext);
+            super(mContext, WindowManagerService.this);
             PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
             mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
                     "KEEP_SCREEN_ON_FLAG");
@@ -6886,6 +6889,10 @@
                         pw.print(mOrientationChanging);
                         pw.print(" mAppFreezing="); pw.println(mAppFreezing);
             }
+            if (mHScale != 1 || mVScale != 1) {
+                pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
+                        pw.print(" mVScale="); pw.println(mVScale);
+            }
         }
 
         @Override
@@ -9198,6 +9205,10 @@
         synchronized (mKeyWaiter) { }
     }
 
+    public void virtualKeyFeedback(KeyEvent event) {
+        mPolicy.keyFeedbackFromInput(event);
+    }
+    
     /**
      * DimAnimator class that controls the dim animation. This holds the surface and
      * all state used for dim animation. 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index e1ca201..8a4b8f9 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -184,8 +184,7 @@
     static final int LOG_BOOT_PROGRESS_ENABLE_SCREEN = 3050;
 
     // The flags that are set for all calls we make to the package manager.
-    static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES
-            | PackageManager.GET_SUPPORTS_DENSITIES;
+    static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
     
     private static final String SYSTEM_SECURE = "ro.secure";
 
@@ -730,6 +729,11 @@
     Configuration mConfiguration = new Configuration();
 
     /**
+     * Hardware-reported OpenGLES version.
+     */
+    final int GL_ES_VERSION;
+
+    /**
      * List of initialization arguments to pass to all processes when binding applications to them.
      * For example, references to the commonly used services.
      */
@@ -1402,6 +1406,9 @@
         mUsageStatsService = new UsageStatsService( new File(
                 systemDir, "usagestats").toString());
 
+        GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
+            ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
+
         mConfiguration.makeDefault();
         mProcessStats.init();
         
@@ -11889,6 +11896,7 @@
                     && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
                 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
             }
+            config.reqGlEsVersion = GL_ES_VERSION;
         }
         return config;
     }
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index c8db95b..33e793b 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -22,6 +22,7 @@
 import android.bluetooth.BluetoothError;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothIntent;
+import android.bluetooth.BluetoothPbap;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -301,6 +302,7 @@
     private IconData mBluetoothData;
     private int mBluetoothHeadsetState;
     private int mBluetoothA2dpState;
+    private int mBluetoothPbapState;
     private boolean mBluetoothEnabled;
 
     // wifi
@@ -378,7 +380,8 @@
             }
             else if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION) ||
                     action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION) ||
-                    action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
+                    action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION) ||
+                    action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
                 updateBluetooth(intent);
             }
             else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) ||
@@ -478,6 +481,7 @@
         }
         mBluetoothA2dpState = BluetoothA2dp.STATE_DISCONNECTED;
         mBluetoothHeadsetState = BluetoothHeadset.STATE_DISCONNECTED;
+        mBluetoothPbapState = BluetoothPbap.STATE_DISCONNECTED;
         mService.setIconVisibility(mBluetoothIcon, mBluetoothEnabled);
 
         // Gps status
@@ -527,6 +531,7 @@
         filter.addAction(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION);
         filter.addAction(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION);
         filter.addAction(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
+        filter.addAction(BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
@@ -1084,13 +1089,17 @@
         } else if (action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
             mBluetoothA2dpState = intent.getIntExtra(BluetoothA2dp.SINK_STATE,
                     BluetoothA2dp.STATE_DISCONNECTED);
+        } else if (action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
+            mBluetoothPbapState = intent.getIntExtra(BluetoothPbap.PBAP_STATE,
+                    BluetoothPbap.STATE_DISCONNECTED);
         } else {
             return;
         }
 
         if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED ||
                 mBluetoothA2dpState == BluetoothA2dp.STATE_CONNECTED ||
-                mBluetoothA2dpState == BluetoothA2dp.STATE_PLAYING) {
+                mBluetoothA2dpState == BluetoothA2dp.STATE_PLAYING ||
+                mBluetoothPbapState == BluetoothPbap.STATE_CONNECTED) {
             iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth_connected;
         }
 
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index a7ac2bc..ebdac4e 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -1225,8 +1225,8 @@
      * Request the device MDN / H_SID / H_NID / MIN.
      * "response" is const char **
      *   [0] is MDN if CDMA subscription is available
-     *   [1] is H_SID (Home SID) if CDMA subscription is available
-     *   [2] is H_NID (Home NID) if CDMA subscription is available
+     *   [1] is H_SID (Home SID) in hexadecimal if CDMA subscription is available
+     *   [2] is H_NID (Home NID) in hexadecimal if CDMA subscription is available
      *   [3] is MIN (10 digits, MIN2+MIN1) if CDMA subscription is available
      */
     public void getCDMASubscription(Message response);
diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java
index 92f6cb8..e6fd0a0 100644
--- a/telephony/java/com/android/internal/telephony/Connection.java
+++ b/telephony/java/com/android/internal/telephony/Connection.java
@@ -56,7 +56,8 @@
         CDMA_RETRY_ORDER,               /* requeseted service is rejected, retry delay is set */
         CDMA_ACCESS_FAILURE,
         CDMA_PREEMPTED,
-        CDMA_NOT_EMERGENCY              /* not an emergency call */
+        CDMA_NOT_EMERGENCY,              /* not an emergency call */
+        ERROR_UNSPECIFIED
     }
 
     Object userData;
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 0bb2df1..769226e 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -1266,6 +1266,13 @@
     boolean disableDataConnectivity();
 
     /**
+     * Report the current state of data connectivity (enabled or disabled)
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    boolean isDataConnectivityEnabled();
+
+    /**
      * Enables the specified APN type. Only works for "special" APN types,
      * i.e., not the default APN.
      * @param type The desired APN type. Cannot be {@link #APN_TYPE_DEFAULT}.
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index 979f0cd..30d56da 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -614,6 +614,10 @@
         return mActivePhone.disableApnType(type);
     }
 
+    public boolean isDataConnectivityEnabled() {
+        return mActivePhone.isDataConnectivityEnabled();
+    }
+
     public boolean isDataConnectivityPossible() {
         return mActivePhone.isDataConnectivityPossible();
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index bdcea92..aec7aee 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -508,6 +508,10 @@
         return false;
     }
 
+    public boolean isDataConnectivityEnabled() {
+        return mDataConnection.getDataEnabled();
+    }
+
     public boolean isDataConnectivityPossible() {
         boolean noData = mDataConnection.getDataEnabled() &&
                 getDataConnectionState() == DataState.DISCONNECTED;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index 905dedf..69ef0e3 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -435,8 +435,10 @@
                 } else if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY
                         && phone.getIccCard().getState() != RuimCard.State.READY) {
                     return DisconnectCause.ICC_ERROR;
-                } else {
+                } else if (causeCode==CallFailCause.NORMAL_CLEARING) {
                     return DisconnectCause.NORMAL;
+                } else {
+                    return DisconnectCause.ERROR_UNSPECIFIED;
                 }
         }
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index e785709..d5da666 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -401,11 +401,11 @@
                     // TODO: Only grabbing the first SID/NID for now.
                     if (cdmaSubscription[1] != null) {
                         String[] sid = cdmaSubscription[1].split(",");
-                        mHomeSystemId = sid.length > 0 ? Integer.parseInt(sid[0]) : 0;
+                        mHomeSystemId = sid.length > 0 ? Integer.parseInt(sid[0], 16) : 0;
                     }
                     if (cdmaSubscription[2] != null) {
                         String[] nid = cdmaSubscription[2].split(",");
-                        mHomeNetworkId = nid.length > 0 ? Integer.parseInt(nid[0]) : 0;
+                        mHomeNetworkId = nid.length > 0 ? Integer.parseInt(nid[0], 16) : 0;
                     }
                     mMin = cdmaSubscription[3];
                     mPrlVersion = cdmaSubscription[4];
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index c085739..30adc52 100755
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -584,38 +584,6 @@
         }
     }
 
-    private static CdmaSmsAddress parseCdmaSmsAddr(String addrStr) {
-        // see C.S0015-B, v2.0, 3.4.3.3
-        CdmaSmsAddress addr = new CdmaSmsAddress();
-        addr.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
-        try {
-            addr.origBytes = addrStr.getBytes("UTF-8");
-            for (int index = 0; index < addr.origBytes.length; index++) {
-                if (addr.origBytes[index] >= '0' && addr.origBytes[index] <= '9') {
-                    if (addr.origBytes[index] == '0') {
-                        addr.origBytes[index] = 10;
-                    } else {
-                        addr.origBytes[index] -= '0';
-                    }
-                } else if (addr.origBytes[index] == '*') {
-                    addr.origBytes[index] = 11;
-                } else if (addr.origBytes[index] == '#') {
-                    addr.origBytes[index] = 12;
-                } else {
-                    return null;
-                }
-            }
-        } catch  (java.io.UnsupportedEncodingException ex) {
-            Log.e(LOG_TAG, "CDMA address parsing failed: " + ex);
-            return null;
-        }
-        addr.numberOfDigits = (byte)addr.origBytes.length;
-        addr.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
-        addr.numberPlan = CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY;
-        addr.ton = CdmaSmsAddress.TON_UNKNOWN;
-        return addr;
-    }
-
     /**
      * Set the nextMessageId to a random value between 0 and 65536
      * See C.S0015-B, v2.0, 4.3.1.5
@@ -642,7 +610,13 @@
          * TODO(cleanup): give this function a more meaningful name.
          */
 
-        CdmaSmsAddress destAddr = parseCdmaSmsAddr(destAddrStr);
+        /**
+         * TODO(cleanup): Make returning null from the getSubmitPdu
+         * variations meaningful -- clean up the error feedback
+         * mechanism, and avoid null pointer exceptions.
+         */
+
+        CdmaSmsAddress destAddr = CdmaSmsAddress.parse(destAddrStr);
         if (destAddr == null) return null;
 
         BearerData bearerData = new BearerData();
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index 2b32872..13cea99 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -624,6 +624,12 @@
         return rawData;
     }
 
+    /*
+     * TODO(cleanup): CdmaSmsAddress encoding should make use of
+     * CdmaSmsAddress.parse provided that DTMF encoding is unified,
+     * and the difference in 4bit vs 8bit is resolved.
+     */
+
     private static void encodeCdmaSmsAddress(CdmaSmsAddress addr) throws CodingException {
         if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
             try {
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
index 4d799665..d9cc2c6 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
@@ -16,7 +16,10 @@
 
 package com.android.internal.telephony.cdma.sms;
 
+import android.util.SparseBooleanArray;
+
 import com.android.internal.telephony.SmsAddress;
+import com.android.internal.telephony.cdma.sms.UserData;
 import com.android.internal.util.HexDump;
 
 public class CdmaSmsAddress extends SmsAddress {
@@ -43,7 +46,8 @@
 
     /**
      * Number Types for data networks.
-     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     * (See 3GPP2 C.S005-D, table2.7.1.3.2.4-2 for complete table)
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3 for data network subset)
      * NOTE: value is stored in the parent class ton field.
      */
     static public final int TON_UNKNOWN                   = 0x00;
@@ -98,10 +102,127 @@
         builder.append(", numberPlan=" + numberPlan);
         builder.append(", numberOfDigits=" + numberOfDigits);
         builder.append(", ton=" + ton);
-        builder.append(", address=" + address);
+        builder.append(", address=\"" + address + "\"");
         builder.append(", origBytes=" + HexDump.toHexString(origBytes));
         builder.append(" }");
         return builder.toString();
     }
 
+    /*
+     * TODO(cleanup): Refactor the parsing for addresses to better
+     * share code and logic with GSM.  Also, gather all DTMF/BCD
+     * processing code in one place.
+     */
+
+    private static byte[] parseToDtmf(String address) {
+        int digits = address.length();
+        byte[] result = new byte[digits];
+        for (int i = 0; i < digits; i++) {
+            char c = address.charAt(i);
+            int val = 0;
+            if ((c >= '1') && (c <= '9')) val = c - '0';
+            else if (c == '0') val = 10;
+            else if (c == '*') val = 11;
+            else if (c == '#') val = 12;
+            else return null;
+            result[i] = (byte)val;
+        }
+        return result;
+    }
+
+    private static final char[] numericCharsDialable = {
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#'
+    };
+
+    private static final char[] numericCharsSugar = {
+        '(', ')', ' ', '-', '+'
+    };
+
+    private static final SparseBooleanArray numericCharDialableMap = new SparseBooleanArray (
+            numericCharsDialable.length + numericCharsSugar.length);
+    static {
+        for (int i = 0; i < numericCharsDialable.length; i++) {
+            numericCharDialableMap.put(numericCharsDialable[i], true);
+        }
+        for (int i = 0; i < numericCharsSugar.length; i++) {
+            numericCharDialableMap.put(numericCharsSugar[i], false);
+        }
+    }
+
+    /**
+     * Given a numeric address string, return the string without
+     * syntactic sugar, meaning parens, spaces, hyphens/minuses, or
+     * plus signs.  If the input string contains non-numeric
+     * non-punctuation characters, return null.
+     */
+    private static String filterNumericSugar(String address) {
+        StringBuilder builder = new StringBuilder();
+        int len = address.length();
+        for (int i = 0; i < len; i++) {
+            char c = address.charAt(i);
+            int mapIndex = numericCharDialableMap.indexOfKey(c);
+            if (mapIndex < 0) return null;
+            if (! numericCharDialableMap.valueAt(mapIndex)) continue;
+            builder.append(c);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Given a string, return the string without whitespace,
+     * including CR/LF.
+     */
+    private static String filterWhitespace(String address) {
+        StringBuilder builder = new StringBuilder();
+        int len = address.length();
+        for (int i = 0; i < len; i++) {
+            char c = address.charAt(i);
+            if ((c == ' ') || (c == '\r') || (c == '\n') || (c == '\t')) continue;
+            builder.append(c);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Given a string, create a corresponding CdmaSmsAddress object.
+     *
+     * The result will be null if the input string is not
+     * representable using printable ASCII.
+     *
+     * For numeric addresses, the string is cleaned up by removing
+     * common punctuation.  For alpha addresses, the string is cleaned
+     * up by removing whitespace.
+     */
+    public static CdmaSmsAddress parse(String address) {
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        addr.address = address;
+        addr.ton = CdmaSmsAddress.TON_UNKNOWN;
+        byte[] origBytes = null;
+        String filteredAddr = filterNumericSugar(address);
+        if (filteredAddr != null) {
+            origBytes = parseToDtmf(filteredAddr);
+        }
+        if (origBytes != null) {
+            addr.digitMode = DIGIT_MODE_4BIT_DTMF;
+            addr.numberMode = NUMBER_MODE_NOT_DATA_NETWORK;
+            if (address.indexOf('+') != -1) {
+                addr.ton = TON_INTERNATIONAL_OR_IP;
+            }
+        } else {
+            filteredAddr = filterWhitespace(address);
+            origBytes = UserData.stringToAscii(filteredAddr);
+            if (origBytes == null) {
+                return null;
+            }
+            addr.digitMode = DIGIT_MODE_8BIT_CHAR;
+            addr.numberMode = NUMBER_MODE_DATA_NETWORK;
+            if (address.indexOf('@') != -1) {
+                addr.ton = TON_NATIONAL_OR_EMAIL;
+            }
+        }
+        addr.origBytes = origBytes;
+        addr.numberOfDigits = origBytes.length;
+        return addr;
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
index 04796b8..54c1f80 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
@@ -92,6 +92,26 @@
         charToAscii.put('\n', ASCII_CR_INDEX);
     }
 
+    /*
+     * TODO(cleanup): Move this very generic functionality somewhere
+     * more general.
+     */
+    /**
+     * Given a string generate a corresponding ASCII-encoded byte
+     * array, but limited to printable characters.  If the input
+     * contains unprintable characters, return null.
+     */
+    public static byte[] stringToAscii(String str) {
+        int len = str.length();
+        byte[] result = new byte[len];
+        for (int i = 0; i < len; i++) {
+            int charCode = charToAscii.get(str.charAt(i), -1);
+            if (charCode == -1) return null;
+            result[i] = (byte)charCode;
+        }
+        return result;
+    }
+
     /**
      * Mapping for IA5 values less than 32 are flow control signals
      * and not used here.
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index ebbf096..6f89288 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -1169,6 +1169,10 @@
         return mDataConnection.getDnsServers(apnType);
     }
 
+    public boolean isDataConnectivityEnabled() {
+        return mDataConnection.getDataEnabled();
+    }
+
     /**
      * The only circumstances under which we report that data connectivity is not
      * possible are
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
index d93ca1d..2091fb6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
@@ -381,10 +381,14 @@
                     } else if (phone.mSST.rs.isCsNormalRestricted()) {
                         return DisconnectCause.CS_RESTRICTED_NORMAL;
                     } else {
-                        return DisconnectCause.NORMAL;
+                        return DisconnectCause.ERROR_UNSPECIFIED;
                     }
-                } else {
+                } else if (causeCode == CallFailCause.NORMAL_CLEARING) {
                     return DisconnectCause.NORMAL;
+                } else {
+                    // If nothing else matches, report unknown call drop reason
+                    // to app, not NORMAL call end.
+                    return DisconnectCause.ERROR_UNSPECIFIED;
                 }
         }
     }
diff --git a/test-runner/android/test/RenamingDelegatingContext.java b/test-runner/android/test/RenamingDelegatingContext.java
index d780502..0ea43ab 100644
--- a/test-runner/android/test/RenamingDelegatingContext.java
+++ b/test-runner/android/test/RenamingDelegatingContext.java
@@ -6,6 +6,8 @@
 import android.content.ContextWrapper;
 import android.content.ContentProvider;
 import android.database.sqlite.SQLiteDatabase;
+import android.os.FileUtils;
+import android.util.Log;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -22,6 +24,8 @@
 
     private Context mFileContext;
     private String mFilePrefix = null;
+    private File mCacheDir;
+    private final Object mSync = new Object();
 
     private Set<String> mDatabaseNames = Sets.newHashSet();
     private Set<String> mFileNames = Sets.newHashSet();
@@ -184,6 +188,32 @@
     public String[] fileList() {
         return mFileNames.toArray(new String[]{});
     }
+    
+    /**
+     * In order to support calls to getCacheDir(), we create a temp cache dir (inside the real
+     * one) and return it instead.  This code is basically getCacheDir(), except it uses the real
+     * cache dir as the parent directory and creates a test cache dir inside that.
+     */
+    @Override
+    public File getCacheDir() {
+        synchronized (mSync) {
+            if (mCacheDir == null) {
+                mCacheDir = new File(mFileContext.getCacheDir(), renamedFileName("cache"));
+            }
+            if (!mCacheDir.exists()) {
+                if(!mCacheDir.mkdirs()) {
+                    Log.w("RenamingDelegatingContext", "Unable to create cache directory");
+                    return null;
+                }
+                FileUtils.setPermissions(
+                        mCacheDir.getPath(),
+                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+                        -1, -1);
+            }
+        }
+        return mCacheDir;
+    }
+
 
 //    /**
 //     * Given an array of files returns only those whose names indicate that they belong to this
diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml
index 845f547..d94327a 100644
--- a/tests/AndroidTests/AndroidManifest.xml
+++ b/tests/AndroidTests/AndroidManifest.xml
@@ -52,6 +52,7 @@
 
     <uses-permission android:name="com.android.unit_tests.permission.TEST_GRANTED" />
 
+    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
     <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
     <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.ALL_SERVICES" />
     <uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" />
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
index f0ba573..90a2917 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
@@ -38,6 +38,67 @@
     private final static String LOG_TAG = "CDMA";
 
     @SmallTest
+    public void testCdmaSmsAddrParsing() throws Exception {
+        CdmaSmsAddress addr = CdmaSmsAddress.parse("6502531000");
+        assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+        assertEquals(addr.numberOfDigits, 10);
+        assertEquals(addr.origBytes.length, 10);
+        byte[] data = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
+        for (int i = 0; i < data.length; i++) {
+            assertEquals(addr.origBytes[i], data[i]);
+        }
+        addr = CdmaSmsAddress.parse("(650) 253-1000");
+        assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+        assertEquals(addr.numberOfDigits, 10);
+        assertEquals(addr.origBytes.length, 10);
+        byte[] data2 = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
+        for (int i = 0; i < data2.length; i++) {
+            assertEquals(addr.origBytes[i], data2[i]);
+        }
+        addr = CdmaSmsAddress.parse("(+886) 917 222 555");
+        assertEquals(addr.ton, CdmaSmsAddress.TON_INTERNATIONAL_OR_IP);
+        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+        assertEquals(addr.numberOfDigits, 12);
+        assertEquals(addr.origBytes.length, 12);
+        byte[] data3 = {8, 8, 6, 9, 1, 7, 2, 2, 2, 5, 5, 5};
+        for (int i = 0; i < data3.length; i++) {
+            assertEquals(addr.origBytes[i], data3[i]);
+        }
+        addr = CdmaSmsAddress.parse("(650) *253-1000 #600");
+        byte[] data4 = {6, 5, 10, 11, 2, 5, 3, 1, 10, 10, 10, 12, 6, 10, 10};
+        for (int i = 0; i < data4.length; i++) {
+            assertEquals(addr.origBytes[i], data4[i]);
+        }
+        String input = "x@y.com,a@b.com";
+        addr = CdmaSmsAddress.parse(input);
+        assertEquals(addr.ton, CdmaSmsAddress.TON_NATIONAL_OR_EMAIL);
+        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR);
+        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK);
+        assertEquals(addr.numberOfDigits, 15);
+        assertEquals(addr.origBytes.length, 15);
+        assertEquals(new String(addr.origBytes), input);
+        addr = CdmaSmsAddress.parse("foo bar");
+        assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR);
+        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK);
+        assertEquals(addr.numberOfDigits, 6);
+        assertEquals(addr.origBytes.length, 6);
+        assertEquals(new String(addr.origBytes), "foobar");
+        addr = CdmaSmsAddress.parse("f\noo\tb   a\rr");
+        assertEquals(new String(addr.origBytes), "foobar");
+        assertEquals(CdmaSmsAddress.parse("f\u0000oo bar"), null);
+        assertEquals(CdmaSmsAddress.parse("f\u0007oo bar"), null);
+        assertEquals(CdmaSmsAddress.parse("f\u0080oo bar"), null);
+        assertEquals(CdmaSmsAddress.parse("f\u1ECFboo\u001fbar"), null);
+        assertEquals(CdmaSmsAddress.parse("f\u0080oo bar"), null);
+    }
+
+    @SmallTest
     public void testUserData7bitGsm() throws Exception {
         String pdu = "00031040900112488ea794e074d69e1b7392c270326cde9e98";
         BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java
index 4c5fefc..e48a57b 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java
@@ -23,14 +23,11 @@
 import android.app.SearchManager;
 import android.content.ComponentName;
 import android.content.Context;
-import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.server.search.SearchableInfo;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
-import android.util.AndroidRuntimeException;
 
 /**
  * To launch this test from the command line:
@@ -98,22 +95,6 @@
                 ServiceManager.getService(Context.SEARCH_SERVICE));
     }
 
-    // Checks that the search UI is visible.
-    private void assertSearchVisible() {
-        SearchManager searchManager = (SearchManager)
-                mContext.getSystemService(Context.SEARCH_SERVICE);
-        assertTrue("SearchManager thinks search UI isn't visible when it should be",
-                searchManager.isVisible());
-    }
-
-    // Checks that the search UI is not visible.
-    private void assertSearchNotVisible() {
-        SearchManager searchManager = (SearchManager)
-                mContext.getSystemService(Context.SEARCH_SERVICE);
-        assertFalse("SearchManager thinks search UI is visible when it shouldn't be",
-                searchManager.isVisible());
-    }
-
     /**
      * The goal of this test is to confirm that we can obtain
      * a search manager interface.
@@ -157,57 +138,34 @@
     }
 
     /**
-     * Tests that rapid calls to start-stop-start doesn't cause problems.
-     */
-    @MediumTest
-    public void testSearchManagerFastInvocations() throws Exception {
-         SearchManager searchManager = (SearchManager)
-                 mContext.getSystemService(Context.SEARCH_SERVICE);
-         assertNotNull(searchManager);
-         assertSearchNotVisible();
-
-         searchManager.startSearch(null, false, SEARCHABLE_ACTIVITY, null, false);
-         assertSearchVisible();
-         searchManager.stopSearch();
-         searchManager.startSearch(null, false, SEARCHABLE_ACTIVITY, null, false);
-         searchManager.stopSearch();
-         assertSearchNotVisible();
-    }
-
-    /**
-     * Tests that startSearch() is idempotent.
+     * Tests that startSearch() can be called multiple times without stopSearch()
+     * in between.
      */
     @MediumTest
     public void testStartSearchIdempotent() throws Exception {
          SearchManager searchManager = (SearchManager)
                  mContext.getSystemService(Context.SEARCH_SERVICE);
          assertNotNull(searchManager);
-         assertSearchNotVisible();
 
          searchManager.startSearch(null, false, SEARCHABLE_ACTIVITY, null, false);
          searchManager.startSearch(null, false, SEARCHABLE_ACTIVITY, null, false);
-         assertSearchVisible();
          searchManager.stopSearch();
-         assertSearchNotVisible();
     }
 
     /**
-     * Tests that stopSearch() is idempotent and can be called when the search UI is not visible.
+     * Tests that stopSearch() can be called when the search UI is not visible and can be
+     * called multiple times without startSearch() in between.
      */
     @MediumTest
     public void testStopSearchIdempotent() throws Exception {
          SearchManager searchManager = (SearchManager)
                  mContext.getSystemService(Context.SEARCH_SERVICE);
          assertNotNull(searchManager);
-         assertSearchNotVisible();
          searchManager.stopSearch();
-         assertSearchNotVisible();
 
          searchManager.startSearch(null, false, SEARCHABLE_ACTIVITY, null, false);
-         assertSearchVisible();
          searchManager.stopSearch();
          searchManager.stopSearch();
-         assertSearchNotVisible();
     }
 
     /**
@@ -219,28 +177,19 @@
         SearchManager searchManager = (SearchManager)
                 mContext.getSystemService(Context.SEARCH_SERVICE);
         assertNotNull(searchManager);
-        assertSearchNotVisible();
 
         // These tests should simply run to completion w/o exceptions
         searchManager.startSearch(null, false, SEARCHABLE_ACTIVITY, null, false);
-        assertSearchVisible();
         searchManager.stopSearch();
-        assertSearchNotVisible();
 
         searchManager.startSearch("", false, SEARCHABLE_ACTIVITY, null, false);
-        assertSearchVisible();
         searchManager.stopSearch();
-        assertSearchNotVisible();
 
         searchManager.startSearch("test search string", false, SEARCHABLE_ACTIVITY, null, false);
-        assertSearchVisible();
         searchManager.stopSearch();
-        assertSearchNotVisible();
 
         searchManager.startSearch("test search string", true, SEARCHABLE_ACTIVITY, null, false);
-        assertSearchVisible();
         searchManager.stopSearch();
-        assertSearchNotVisible();
     }
 
 }
diff --git a/tests/CoreTests/android/AndroidManifest.xml b/tests/CoreTests/android/AndroidManifest.xml
index 4809f844..98cc9e5 100644
--- a/tests/CoreTests/android/AndroidManifest.xml
+++ b/tests/CoreTests/android/AndroidManifest.xml
@@ -30,6 +30,7 @@
     <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
     <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/CoreTests/android/database/MatrixCursorTest.java b/tests/CoreTests/android/database/MatrixCursorTest.java
index fb8a12f..cddc6c4 100644
--- a/tests/CoreTests/android/database/MatrixCursorTest.java
+++ b/tests/CoreTests/android/database/MatrixCursorTest.java
@@ -32,6 +32,12 @@
         cursor.newRow().add(null);
         cursor.moveToNext();
         assertTrue(cursor.isNull(0));
+        assertNull(cursor.getString(0));
+        assertEquals(0, cursor.getShort(0));
+        assertEquals(0, cursor.getInt(0));
+        assertEquals(0L, cursor.getLong(0));
+        assertEquals(0.0f, cursor.getFloat(0));
+        assertEquals(0.0d, cursor.getDouble(0));
     }
 
     public void testMatrixCursor() {
diff --git a/tests/DpiTest/res/drawable-hdpi/npatch240dpi.9.png b/tests/DpiTest/res/drawable-hdpi/npatch240dpi.9.png
new file mode 100644
index 0000000..a362b0f
--- /dev/null
+++ b/tests/DpiTest/res/drawable-hdpi/npatch240dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-hdpi/smlnpatch240dpi.9.png b/tests/DpiTest/res/drawable-hdpi/smlnpatch240dpi.9.png
new file mode 100644
index 0000000..84bdcb0
--- /dev/null
+++ b/tests/DpiTest/res/drawable-hdpi/smlnpatch240dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-ldpi/npatch120dpi.9.png b/tests/DpiTest/res/drawable-ldpi/npatch120dpi.9.png
new file mode 100644
index 0000000..0d8115b
--- /dev/null
+++ b/tests/DpiTest/res/drawable-ldpi/npatch120dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-ldpi/smlnpatch120dpi.9.png b/tests/DpiTest/res/drawable-ldpi/smlnpatch120dpi.9.png
new file mode 100644
index 0000000..de8d607
--- /dev/null
+++ b/tests/DpiTest/res/drawable-ldpi/smlnpatch120dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable/npatch160dpi.9.png b/tests/DpiTest/res/drawable/npatch160dpi.9.png
new file mode 100644
index 0000000..44d89a9
--- /dev/null
+++ b/tests/DpiTest/res/drawable/npatch160dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable/smlnpatch160dpi.9.png b/tests/DpiTest/res/drawable/smlnpatch160dpi.9.png
new file mode 100644
index 0000000..76c4ae8
--- /dev/null
+++ b/tests/DpiTest/res/drawable/smlnpatch160dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
index 49fff57..68220a1 100644
--- a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
+++ b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
@@ -34,6 +34,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
 import android.util.DisplayMetrics;
+import android.util.Log;
 
 public class DpiTestActivity extends Activity {
     public DpiTestActivity() {
@@ -52,14 +53,13 @@
             // be doing it.
             Application app = ActivityThread.currentActivityThread().getApplication();
             ApplicationInfo ai = app.getPackageManager().getApplicationInfo(
-                    "com.google.android.test.dpi",
-                    PackageManager.GET_SUPPORTS_DENSITIES);
+                    "com.google.android.test.dpi", 0);
             if (noCompat) {
                 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS
                     | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS
                     | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS
-                    | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
-                ai.supportsDensities = new int[] { ApplicationInfo.ANY_DENSITY };
+                    | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS
+                    | ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
                 app.getResources().setCompatibilityInfo(new CompatibilityInfo(ai));
             }
         } catch (PackageManager.NameNotFoundException e) {
@@ -117,6 +117,13 @@
         addLabelToRoot(root, "No-dpi resource drawable");
         addChildToRoot(root, layout);
 
+        layout = new LinearLayout(this);
+        addNinePatchResourceDrawable(layout, R.drawable.smlnpatch120dpi);
+        addNinePatchResourceDrawable(layout, R.drawable.smlnpatch160dpi);
+        addNinePatchResourceDrawable(layout, R.drawable.smlnpatch240dpi);
+        addLabelToRoot(root, "Prescaled 9-patch resource drawable");
+        addChildToRoot(root, layout);
+
         setContentView(scrollWrap(root));
     }
 
@@ -145,8 +152,8 @@
 
         View view = new View(this);
 
-        final BitmapDrawable d = new BitmapDrawable(bitmap);
-        if (!scale) d.setDensityScale(getResources().getDisplayMetrics());
+        final BitmapDrawable d = new BitmapDrawable(getResources(), bitmap);
+        if (!scale) d.setTargetDensity(getResources().getDisplayMetrics());
         view.setBackgroundDrawable(d);
 
         view.setLayoutParams(new LinearLayout.LayoutParams(d.getIntrinsicWidth(),
@@ -176,6 +183,19 @@
         layout.addView(view);
     }
 
+    private void addNinePatchResourceDrawable(LinearLayout layout, int resource) {
+        View view = new View(this);
+
+        final Drawable d = getResources().getDrawable(resource);
+        view.setBackgroundDrawable(d);
+
+        Log.i("foo", "9-patch #" + Integer.toHexString(resource)
+                + " w=" + d.getIntrinsicWidth() + " h=" + d.getIntrinsicHeight());
+        view.setLayoutParams(new LinearLayout.LayoutParams(
+                d.getIntrinsicWidth()*2, d.getIntrinsicHeight()*2));
+        layout.addView(view);
+    }
+
     private Bitmap loadAndPrintDpi(int id, boolean scale) {
         Bitmap bitmap;
         if (scale) {
diff --git a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java
index 93cb84a..515ddba 100644
--- a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java
+++ b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java
@@ -27,8 +27,10 @@
         super("com.android.frameworktest", AutoCompleteTextViewSimple.class);
     }
 
-    /** Test that the initial popup of the suggestions does not select anything */
-    @MediumTest
+    /** Test that the initial popup of the suggestions does not select anything.
+     *
+     * TODO: test currently fails. Add back MediumTest annotation when fixed.
+     */
     public void testPopupNoSelection() {
         AutoCompleteTextViewSimple theActivity = getActivity();
         AutoCompleteTextView textView = theActivity.getTextView();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
index 48998db..10421de 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
@@ -39,7 +39,7 @@
  * TODO: describe.
  */
 public final class BridgeTypedArray extends TypedArray {
-    
+
     @SuppressWarnings("hiding")
     private BridgeResources mResources;
     private BridgeContext mContext;
@@ -47,7 +47,7 @@
     private IResourceValue[] mData;
     private String[] mNames;
     private final boolean mPlatformFile;
-    
+
     public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
             boolean platformFile) {
         super(null, null, null, 0);
@@ -58,12 +58,12 @@
         mNames = new String[len];
     }
 
-    /** A bridge-specific method that sets a value in the type array */ 
+    /** A bridge-specific method that sets a value in the type array */
     public void bridgeSetValue(int index, String name, IResourceValue value) {
         mData[index] = value;
         mNames[index] = name;
     }
-    
+
     /**
      * Seals the array after all calls to {@link #bridgeSetValue(int, String, IResourceValue)} have
      * been done.
@@ -79,11 +79,11 @@
                 count++;
             }
         }
-        
+
         // allocate the table with an extra to store the size
         mIndices = new int[count+1];
         mIndices[0] = count;
-        
+
         // fill the array with the indices.
         int index = 1;
         for (int i = 0 ; i < mData.length ; i++) {
@@ -100,7 +100,7 @@
     public int length() {
         return mData.length;
     }
-    
+
     /**
      * Return the Resources object this array was loaded from.
      */
@@ -108,13 +108,13 @@
     public Resources getResources() {
         return mResources;
     }
-    
+
     /**
      * Retrieve the styled string value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
-     * @return CharSequence holding string data.  May be styled.  Returns 
+     *
+     * @return CharSequence holding string data.  May be styled.  Returns
      *         null if the attribute is not defined.
      */
     @Override
@@ -129,9 +129,9 @@
 
     /**
      * Retrieve the string value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return String holding string data.  Any styling information is
      * removed.  Returns null if the attribute is not defined.
      */
@@ -140,16 +140,16 @@
         if (mData[index] != null) {
             return mData[index].getValue();
         }
-        
+
         return null;
     }
 
     /**
      * Retrieve the boolean value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined.
-     * 
+     *
      * @return Attribute boolean value, or defValue if not defined.
      */
     @Override
@@ -162,16 +162,16 @@
         if (s != null) {
             return XmlUtils.convertValueToBoolean(s, defValue);
         }
-        
+
         return defValue;
     }
 
     /**
      * Retrieve the integer value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined.
-     * 
+     *
      * @return Attribute int value, or defValue if not defined.
      */
     @Override
@@ -181,7 +181,7 @@
         }
 
         String s = mData[index].getValue();
-        
+
         try {
             return (s == null) ? defValue : XmlUtils.convertValueToInt(s, defValue);
         } catch (NumberFormatException e) {
@@ -192,11 +192,11 @@
         // Check for possible constants and try to find them.
         // Get the map of attribute-constant -> IntegerValue
         Map<String, Integer> map = Bridge.getEnumValues(mNames[index]);
-        
+
         if (map != null) {
             // accumulator to store the value of the 1+ constants.
             int result = 0;
-            
+
             // split the value in case this is a mix of several flags.
             String[] keywords = s.split("\\|");
             for (String keyword : keywords) {
@@ -217,9 +217,9 @@
 
     /**
      * Retrieve the float value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return Attribute float value, or defValue if not defined..
      */
     @Override
@@ -237,23 +237,23 @@
                 mContext.getLogger().warning(String.format(
                         "Unable to convert \"%s\" into a float in attribute \"%2$s\"",
                         s, mNames[index]));
-                
+
                 // we'll return the default value below.
             }
         }
         return defValue;
     }
-    
+
     /**
      * Retrieve the color value for the attribute at <var>index</var>.  If
      * the attribute references a color resource holding a complex
      * {@link android.content.res.ColorStateList}, then the default color from
      * the set is returned.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
+     *
      * @return Attribute color value, or defValue if not defined.
      */
     @Override
@@ -261,7 +261,7 @@
         if (mData[index] == null) {
             return defValue;
         }
-        
+
         String s = mData[index].getValue();
         try {
             return ResourceHelper.getColor(s);
@@ -280,9 +280,9 @@
      * Retrieve the ColorStateList for the attribute at <var>index</var>.
      * The value may be either a single solid color or a reference to
      * a color or complex {@link android.content.res.ColorStateList} description.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return ColorStateList for the attribute, or null if not defined.
      */
     @Override
@@ -296,14 +296,14 @@
         if (value == null) {
             return null;
         }
-        
+
         try {
             int color = ResourceHelper.getColor(value);
             return ColorStateList.valueOf(color);
         } catch (NumberFormatException e) {
             // if it's not a color value, we'll attempt to read the xml based color below.
         }
-        
+
         // let the framework inflate the ColorStateList from the XML file.
         try {
             File f = new File(value);
@@ -311,7 +311,7 @@
                 KXmlParser parser = new KXmlParser();
                 parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
                 parser.setInput(new FileReader(f));
-                
+
                 ColorStateList colorStateList = ColorStateList.createFromXml(
                         mContext.getResources(),
                         // FIXME: we need to know if this resource is platform or not
@@ -325,22 +325,22 @@
 
             // return null below.
         }
-        
+
         // looks like were unable to resolve the color value.
         mContext.getLogger().warning(String.format(
                 "Unable to resolve color value \"%1$s\" in attribute \"%2$s\"",
                 value, mNames[index]));
-        
+
         return null;
     }
-    
+
     /**
      * Retrieve the integer value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
+     *
      * @return Attribute integer value, or defValue if not defined.
      */
     @Override
@@ -362,23 +362,23 @@
                 // The default value is returned below.
             }
         }
-        
+
         return defValue;
     }
 
     /**
-     * Retrieve a dimensional unit attribute at <var>index</var>.  Unit 
-     * conversions are based on the current {@link DisplayMetrics} 
-     * associated with the resources this {@link TypedArray} object 
-     * came from. 
-     * 
+     * Retrieve a dimensional unit attribute at <var>index</var>.  Unit
+     * conversions are based on the current {@link DisplayMetrics}
+     * associated with the resources this {@link TypedArray} object
+     * came from.
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric, or defValue if not defined.
-     * 
+     *
      * @see #getDimensionPixelOffset
      * @see #getDimensionPixelSize
      */
@@ -397,11 +397,11 @@
         } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
             return LayoutParams.WRAP_CONTENT;
         }
-        
+
         if (ResourceHelper.stringToFloat(s, mValue)) {
             return mValue.getDimension(mResources.mMetrics);
         }
-        
+
         // looks like we were unable to resolve the dimension value
         mContext.getLogger().warning(String.format(
                 "Unable to resolve dimension value \"%1$s\" in attribute \"%2$s\"",
@@ -416,14 +416,14 @@
      * {@link #getDimension}, except the returned value is converted to
      * integer pixels for you.  An offset conversion involves simply
      * truncating the base value to an integer.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric and truncated to integer pixels, or defValue if not defined.
-     * 
+     *
      * @see #getDimension
      * @see #getDimensionPixelSize
      */
@@ -439,14 +439,14 @@
      * integer pixels for use as a size.  A size conversion involves
      * rounding the base value, and ensuring that a non-zero base value
      * is at least one pixel in size.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric and truncated to integer pixels, or defValue if not defined.
-     *  
+     *
      * @see #getDimension
      * @see #getDimensionPixelOffset
      */
@@ -465,7 +465,7 @@
         } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
             return LayoutParams.WRAP_CONTENT;
         }
-        
+
         // FIXME huh?
 
         float f = getDimension(index, defValue);
@@ -483,11 +483,11 @@
      * {@link android.view.ViewGroup}'s layout_width and layout_height
      * attributes.  This is only here for performance reasons; applications
      * should use {@link #getDimensionPixelSize}.
-     * 
+     *
      * @param index Index of the attribute to retrieve.
      * @param name Textual name of attribute for error reporting.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric and truncated to integer pixels.
      */
     @Override
@@ -495,20 +495,25 @@
         return getDimensionPixelSize(index, 0);
     }
 
+    @Override
+    public int getLayoutDimension(int index, int defValue) {
+        return getDimensionPixelSize(index, defValue);
+    }
+
     /**
      * Retrieve a fractional unit attribute at <var>index</var>.
-     * 
-     * @param index Index of attribute to retrieve. 
-     * @param base The base value of this fraction.  In other words, a 
+     *
+     * @param index Index of attribute to retrieve.
+     * @param base The base value of this fraction.  In other words, a
      *             standard fraction is multiplied by this value.
-     * @param pbase The parent base value of this fraction.  In other 
+     * @param pbase The parent base value of this fraction.  In other
      *             words, a parent fraction (nn%p) is multiplied by this
      *             value.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute fractional value multiplied by the appropriate 
-     * base value, or defValue if not defined. 
+     *
+     * @return Attribute fractional value multiplied by the appropriate
+     * base value, or defValue if not defined.
      */
     @Override
     public float getFraction(int index, int base, int pbase, float defValue) {
@@ -520,7 +525,7 @@
         if (value == null) {
             return defValue;
         }
-        
+
         if (ResourceHelper.stringToFloat(value, mValue)) {
             return mValue.getFraction(base, pbase);
         }
@@ -529,29 +534,29 @@
         mContext.getLogger().warning(String.format(
                 "Unable to resolve fraction value \"%1$s\" in attribute \"%2$s\"",
                 value, mNames[index]));
-        
+
         return defValue;
     }
 
     /**
      * Retrieve the resource identifier for the attribute at
-     * <var>index</var>.  Note that attribute resource as resolved when 
-     * the overall {@link TypedArray} object is retrieved.  As a 
-     * result, this function will return the resource identifier of the 
-     * final resource value that was found, <em>not</em> necessarily the 
-     * original resource that was specified by the attribute. 
-     * 
+     * <var>index</var>.  Note that attribute resource as resolved when
+     * the overall {@link TypedArray} object is retrieved.  As a
+     * result, this function will return the resource identifier of the
+     * final resource value that was found, <em>not</em> necessarily the
+     * original resource that was specified by the attribute.
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
+     *
      * @return Attribute resource identifier, or defValue if not defined.
      */
     @Override
     public int getResourceId(int index, int defValue) {
         // get the IResource for this index
         IResourceValue resValue = mData[index];
-        
+
         // no data, return the default value.
         if (resValue == null) {
             return defValue;
@@ -562,7 +567,7 @@
             // get the id that will represent this style.
             return mContext.getDynamicIdByStyle((IStyleResourceValue)resValue);
         }
-        
+
         // if the attribute was a reference to an id, and not a declaration of an id (@+id), then
         // the xml attribute value was "resolved" which leads us to a IResourceValue with
         // getType() returning "id" and getName() returning the id name
@@ -583,7 +588,7 @@
         if (value == null) {
             return defValue;
         }
-        
+
         // if the value is just an integer, return it.
         try {
             int i = Integer.parseInt(value);
@@ -601,14 +606,14 @@
         // fact in the android.R and com.android.internal.R classes.
         // The field mPlatformFile will indicate that all IDs are to be looked up in the android R
         // classes exclusively.
-        
+
         // if this is a reference to an id, find it.
         if (value.startsWith("@id/") || value.startsWith("@+") ||
                 value.startsWith("@android:id/")) {
-            
+
             int pos = value.indexOf('/');
             String idName = value.substring(pos + 1);
-            
+
             // if this is a framework id
             if (mPlatformFile || value.startsWith("@android") || value.startsWith("@+android")) {
                 // look for idName in the android R classes
@@ -621,7 +626,7 @@
 
         // not a direct id valid reference? resolve it
         Integer idValue = null;
-        
+
         if (resValue.isFramework()) {
             idValue = Bridge.getResourceValue(resValue.getType(), resValue.getName());
         } else {
@@ -632,7 +637,7 @@
         if (idValue != null) {
             return idValue.intValue();
         }
-        
+
         mContext.getLogger().warning(String.format(
                 "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]));
         return defValue;
@@ -643,9 +648,9 @@
      * gets the resource ID of the selected attribute, and uses
      * {@link Resources#getDrawable Resources.getDrawable} of the owning
      * Resources object to retrieve its Drawable.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return Drawable for the attribute, or null if not defined.
      */
     @Override
@@ -658,13 +663,13 @@
         if (value == null || BridgeConstants.REFERENCE_NULL.equals(value)) {
             return null;
         }
-        
+
         Drawable d = ResourceHelper.getDrawable(value, mContext, mData[index].isFramework());
-        
+
         if (d != null) {
             return d;
         }
-        
+
         // looks like we were unable to resolve the drawable
         mContext.getLogger().warning(String.format(
                 "Unable to resolve drawable \"%1$s\" in attribute \"%2$s\"", value, mNames[index]));
@@ -678,9 +683,9 @@
      * This gets the resource ID of the selected attribute, and uses
      * {@link Resources#getTextArray Resources.getTextArray} of the owning
      * Resources object to retrieve its String[].
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return CharSequence[] for the attribute, or null if not defined.
      */
     @Override
@@ -693,7 +698,7 @@
         if (value != null) {
             return new CharSequence[] { value };
         }
-        
+
         mContext.getLogger().warning(String.format(
                 String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
                 index, mData[index].getName())));
@@ -703,44 +708,44 @@
 
     /**
      * Retrieve the raw TypedValue for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param outValue TypedValue object in which to place the attribute's
      *                 data.
-     * 
-     * @return Returns true if the value was retrieved, else false. 
+     *
+     * @return Returns true if the value was retrieved, else false.
      */
     @Override
     public boolean getValue(int index, TypedValue outValue) {
         if (mData[index] == null) {
             return false;
         }
-        
+
         String s = mData[index].getValue();
-        
+
         return ResourceHelper.stringToFloat(s, outValue);
     }
 
     /**
      * Determines whether there is an attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return True if the attribute has a value, false otherwise.
      */
     @Override
     public boolean hasValue(int index) {
         return mData[index] != null;
     }
-    
+
     /**
-     * Retrieve the raw TypedValue for the attribute at <var>index</var> 
-     * and return a temporary object holding its data.  This object is only 
-     * valid until the next call on to {@link TypedArray}. 
-     * 
+     * Retrieve the raw TypedValue for the attribute at <var>index</var>
+     * and return a temporary object holding its data.  This object is only
+     * valid until the next call on to {@link TypedArray}.
+     *
      * @param index Index of attribute to retrieve.
-     * 
-     * @return Returns a TypedValue object if the attribute is defined, 
+     *
+     * @return Returns a TypedValue object if the attribute is defined,
      *         containing its data; otherwise returns null.  (You will not
      *         receive a TypedValue whose type is TYPE_NULL.)
      */
@@ -749,7 +754,7 @@
         if (getValue(index, mValue)) {
             return mValue;
         }
-        
+
         return null;
     }
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index eda2f2d..f85aadd 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -45,6 +45,8 @@
     /** {@hide} */
     public static final String eapVarName = "eap";
     /** {@hide} */
+    public static final String phase2VarName = "phase2";
+    /** {@hide} */
     public static final String identityVarName = "identity";
     /** {@hide} */
     public static final String anonymousIdentityVarName = "anonymous_identity";
@@ -273,6 +275,11 @@
      */
     public String eap;
     /**
+     * The phase2 authenication could be PAP, MSCHAP, MSCHAP2, GTC.
+     * {@hide}
+     */
+    public String phase2;
+    /**
      * The identity of the user in string,
      * which is used for the authentication.
      * {@hide}
@@ -314,6 +321,7 @@
         for (int i = 0; i < wepKeys.length; i++)
             wepKeys[i] = null;
         eap = null;
+        phase2 = null;
         identity = null;
         anonymousIdentity = null;
         password = null;
@@ -399,6 +407,10 @@
         if (this.eap != null) {
             sbuf.append(eap);
         }
+        sbuf.append('\n').append(" phase2: ");
+        if (this.phase2 != null) {
+            sbuf.append(phase2);
+        }
         sbuf.append('\n').append(" Identity: ");
         if (this.identity != null) {
             sbuf.append(identity);
@@ -486,6 +498,7 @@
         writeBitSet(dest, allowedPairwiseCiphers);
         writeBitSet(dest, allowedGroupCiphers);
         dest.writeString(eap);
+        dest.writeString(phase2);
         dest.writeString(identity);
         dest.writeString(anonymousIdentity);
         dest.writeString(password);
@@ -516,6 +529,7 @@
                 config.allowedPairwiseCiphers = readBitSet(in);
                 config.allowedGroupCiphers    = readBitSet(in);
                 config.eap = in.readString();
+                config.phase2 = in.readString();
                 config.identity = in.readString();
                 config.anonymousIdentity = in.readString();
                 config.password = in.readString();