Merge change I58def690 into eclair-mr2

* changes:
  If openOrCreateDatabase() throws an exception, delete the old db and re-do it. If it still fails, something bad happens, like the directory may have the different permission. Let it throw as WebView needs the db.
diff --git a/Android.mk b/Android.mk
index 2e2fec1..d153ce6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -108,6 +108,7 @@
 	core/java/android/hardware/ISensorService.aidl \
 	core/java/android/net/IConnectivityManager.aidl \
 	core/java/android/os/ICheckinService.aidl \
+	core/java/android/os/IDropBox.aidl \
 	core/java/android/os/IHardwareService.aidl \
 	core/java/android/os/IMessenger.aidl \
 	core/java/android/os/IMountService.aidl \
@@ -216,6 +217,7 @@
 	frameworks/base/core/java/android/appwidget/AppWidgetProviderInfo.aidl \
 	frameworks/base/core/java/android/net/Uri.aidl \
 	frameworks/base/core/java/android/os/Bundle.aidl \
+	frameworks/base/core/java/android/os/DropBoxEntry.aidl \
 	frameworks/base/core/java/android/os/ParcelFileDescriptor.aidl \
 	frameworks/base/core/java/android/os/ParcelUuid.aidl \
 	frameworks/base/core/java/android/view/KeyEvent.aidl \
@@ -372,7 +374,7 @@
 
 ## SDK version identifiers used in the published docs
   # major[.minor] version for current SDK. (full releases only)
-framework_docs_SDK_VERSION:=1.6
+framework_docs_SDK_VERSION:=2.0
   # release version (ie "Release x")  (full releases only)
 framework_docs_SDK_REL_ID:=1
   # name of current SDK directory (full releases only)
diff --git a/api/5.xml b/api/5.xml
index ca2cceb..6148047 100644
--- a/api/5.xml
+++ b/api/5.xml
@@ -112806,6 +112806,58 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.BaseSyncColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="SYNC1"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sync1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC2"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sync2&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC3"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sync3&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC4"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sync4&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.CommonDataKinds"
  extends="java.lang.Object"
  abstract="false"
@@ -112834,6 +112886,49 @@
 >
 </field>
 </interface>
+<interface name="ContactsContract.CommonDataKinds.CommonColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="android.provider.ContactsContract.CommonDataKinds.BaseTypes">
+</implements>
+<field name="DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LABEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data3&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data2&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.CommonDataKinds.Email"
  extends="java.lang.Object"
  abstract="false"
@@ -112842,6 +112937,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getTypeLabel"
  return="java.lang.CharSequence"
  abstract="false"
@@ -112988,6 +113087,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getTypeResource"
  return="int"
  abstract="false"
@@ -113065,6 +113168,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -113107,6 +113212,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getProtocolLabel"
  return="java.lang.CharSequence"
  abstract="false"
@@ -113352,6 +113461,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -113438,6 +113551,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -113469,6 +113584,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getTypeLabel"
  return="java.lang.CharSequence"
  abstract="false"
@@ -113618,6 +113737,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getTypeLabel"
  return="java.lang.CharSequence"
  abstract="false"
@@ -113930,6 +114053,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -113961,6 +114086,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -114146,6 +114275,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -114265,6 +114396,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getTypeLabel"
  return="java.lang.CharSequence"
  abstract="false"
@@ -114457,6 +114592,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -114557,6 +114696,143 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.ContactOptionsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="CUSTOM_RINGTONE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;custom_ringtone&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LAST_TIME_CONTACTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;last_time_contacted&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SEND_TO_VOICEMAIL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;send_to_voicemail&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STARRED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;starred&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TIMES_CONTACTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;times_contacted&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
+<interface name="ContactsContract.ContactStatusColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="CONTACT_PRESENCE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_presence&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_STATUS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_status&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_STATUS_ICON"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_status_icon&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_STATUS_LABEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_status_label&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_STATUS_RES_PACKAGE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_status_res_package&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_STATUS_TIMESTAMP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_status_ts&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.Contacts"
  extends="java.lang.Object"
  abstract="false"
@@ -114567,6 +114843,12 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactOptionsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactStatusColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactsColumns">
+</implements>
 <method name="getLookupUri"
  return="android.net.Uri"
  abstract="false"
@@ -114756,6 +115038,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactsColumns">
+</implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
  transient="false"
@@ -114778,6 +115062,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
  transient="false"
@@ -114800,6 +115086,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
  transient="false"
@@ -114812,6 +115100,69 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.ContactsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="DISPLAY_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;display_name&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="HAS_PHONE_NUMBER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;has_phone_number&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IN_VISIBLE_GROUP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;in_visible_group&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LOOKUP_KEY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;lookup&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;photo_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.Data"
  extends="java.lang.Object"
  abstract="false"
@@ -114820,6 +115171,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getContactLookupUri"
  return="android.net.Uri"
  abstract="false"
@@ -114857,6 +115210,300 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.DataColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="DATA1"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA10"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data10&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA11"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data11&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA12"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data12&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA13"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data13&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA14"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data14&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA15"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data15&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA2"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data2&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA3"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data3&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA4"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data4&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA5"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data5&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA6"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data6&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA7"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data7&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA8"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data8&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA9"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data9&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA_VERSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_version&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IS_PRIMARY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;is_primary&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IS_SUPER_PRIMARY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;is_super_primary&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MIMETYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;mimetype&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RAW_CONTACT_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;raw_contact_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC1"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_sync1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC2"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_sync2&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC3"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_sync3&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC4"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_sync4&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
+<interface name="ContactsContract.DataColumnsWithJoins"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="android.provider.BaseColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactOptionsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactStatusColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
+<implements name="android.provider.ContactsContract.RawContactsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.StatusColumns">
+</implements>
+</interface>
 <class name="ContactsContract.Groups"
  extends="java.lang.Object"
  abstract="false"
@@ -114867,6 +115514,10 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.GroupsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.SyncColumns">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -114910,6 +115561,102 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.GroupsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="DELETED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;deleted&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GROUP_VISIBLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;group_visible&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NOTES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;notes&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOULD_SYNC"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;should_sync&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SUMMARY_COUNT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;summ_count&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SUMMARY_WITH_PHONES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;summ_phones&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYSTEM_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;system_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TITLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;title&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.Intents"
  extends="java.lang.Object"
  abstract="false"
@@ -115328,6 +116075,12 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactOptionsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.PhoneLookupColumns">
+</implements>
 <field name="CONTENT_FILTER_URI"
  type="android.net.Uri"
  transient="false"
@@ -115339,6 +116092,47 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.PhoneLookupColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="LABEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;label&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NUMBER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;number&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;type&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.Presence"
  extends="android.provider.ContactsContract.StatusUpdates"
  abstract="false"
@@ -115356,6 +116150,69 @@
 >
 </constructor>
 </class>
+<interface name="ContactsContract.PresenceColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="CUSTOM_PROTOCOL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;custom_protocol&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;presence_data_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IM_ACCOUNT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;im_account&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IM_HANDLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;im_handle&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PROTOCOL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;protocol&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.QuickContact"
  extends="java.lang.Object"
  abstract="false"
@@ -115458,6 +116315,12 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactOptionsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.RawContactsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.SyncColumns">
+</implements>
 <method name="getContactLookupUri"
  return="android.net.Uri"
  abstract="false"
@@ -115560,6 +116423,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
  transient="false"
@@ -115582,6 +116447,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
  transient="false"
@@ -115605,6 +116472,47 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.RawContactsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="AGGREGATION_MODE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;aggregation_mode&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DELETED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;deleted&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.RawContactsEntity"
  extends="java.lang.Object"
  abstract="false"
@@ -115615,6 +116523,10 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
+<implements name="android.provider.ContactsContract.RawContactsColumns">
+</implements>
 <field name="CONTENT_TYPE"
  type="java.lang.String"
  transient="false"
@@ -115656,6 +116568,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.SettingsColumns">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -115689,6 +116603,165 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.SettingsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="ACCOUNT_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;account_name&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACCOUNT_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;account_type&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ANY_UNSYNCED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;any_unsynced&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOULD_SYNC"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;should_sync&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNGROUPED_COUNT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;summ_count&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNGROUPED_VISIBLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;ungrouped_visible&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNGROUPED_WITH_PHONES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;summ_phones&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
+<interface name="ContactsContract.StatusColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="PRESENCE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;mode&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;status&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ICON"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;status_icon&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_LABEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;status_label&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_RES_PACKAGE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;status_res_package&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_TIMESTAMP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;status_ts&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.StatusUpdates"
  extends="java.lang.Object"
  abstract="false"
@@ -115697,6 +116770,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.PresenceColumns">
+</implements>
+<implements name="android.provider.ContactsContract.StatusColumns">
+</implements>
 <method name="getPresenceIconResourceId"
  return="int"
  abstract="false"
@@ -115756,6 +116833,71 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.SyncColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="android.provider.ContactsContract.BaseSyncColumns">
+</implements>
+<field name="ACCOUNT_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;account_name&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACCOUNT_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;account_type&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DIRTY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;dirty&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sourceid&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VERSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;version&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.SyncState"
  extends="java.lang.Object"
  abstract="false"
diff --git a/api/current.xml b/api/current.xml
index 15ea245..290bd80 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -112806,6 +112806,58 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.BaseSyncColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="SYNC1"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sync1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC2"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sync2&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC3"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sync3&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC4"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sync4&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.CommonDataKinds"
  extends="java.lang.Object"
  abstract="false"
@@ -112834,6 +112886,49 @@
 >
 </field>
 </interface>
+<interface name="ContactsContract.CommonDataKinds.CommonColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="android.provider.ContactsContract.CommonDataKinds.BaseTypes">
+</implements>
+<field name="DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LABEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data3&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data2&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.CommonDataKinds.Email"
  extends="java.lang.Object"
  abstract="false"
@@ -112842,6 +112937,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getTypeLabel"
  return="java.lang.CharSequence"
  abstract="false"
@@ -112988,6 +113087,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getTypeResource"
  return="int"
  abstract="false"
@@ -113065,6 +113168,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -113107,6 +113212,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getProtocolLabel"
  return="java.lang.CharSequence"
  abstract="false"
@@ -113352,6 +113461,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -113438,6 +113551,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -113469,6 +113584,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getTypeLabel"
  return="java.lang.CharSequence"
  abstract="false"
@@ -113618,6 +113737,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getTypeLabel"
  return="java.lang.CharSequence"
  abstract="false"
@@ -113930,6 +114053,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -113961,6 +114086,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -114146,6 +114275,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -114265,6 +114396,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getTypeLabel"
  return="java.lang.CharSequence"
  abstract="false"
@@ -114457,6 +114592,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.CommonDataKinds.CommonColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -114557,6 +114696,143 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.ContactOptionsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="CUSTOM_RINGTONE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;custom_ringtone&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LAST_TIME_CONTACTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;last_time_contacted&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SEND_TO_VOICEMAIL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;send_to_voicemail&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STARRED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;starred&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TIMES_CONTACTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;times_contacted&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
+<interface name="ContactsContract.ContactStatusColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="CONTACT_PRESENCE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_presence&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_STATUS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_status&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_STATUS_ICON"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_status_icon&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_STATUS_LABEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_status_label&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_STATUS_RES_PACKAGE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_status_res_package&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_STATUS_TIMESTAMP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_status_ts&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.Contacts"
  extends="java.lang.Object"
  abstract="false"
@@ -114567,6 +114843,12 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactOptionsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactStatusColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactsColumns">
+</implements>
 <method name="getLookupUri"
  return="android.net.Uri"
  abstract="false"
@@ -114756,6 +115038,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactsColumns">
+</implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
  transient="false"
@@ -114778,6 +115062,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
  transient="false"
@@ -114800,6 +115086,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
  transient="false"
@@ -114812,6 +115100,69 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.ContactsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="DISPLAY_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;display_name&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="HAS_PHONE_NUMBER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;has_phone_number&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IN_VISIBLE_GROUP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;in_visible_group&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LOOKUP_KEY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;lookup&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;photo_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.Data"
  extends="java.lang.Object"
  abstract="false"
@@ -114820,6 +115171,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
+</implements>
 <method name="getContactLookupUri"
  return="android.net.Uri"
  abstract="false"
@@ -114857,6 +115210,300 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.DataColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="DATA1"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA10"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data10&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA11"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data11&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA12"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data12&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA13"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data13&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA14"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data14&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA15"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data15&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA2"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data2&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA3"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data3&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA4"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data4&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA5"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data5&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA6"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data6&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA7"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data7&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA8"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data8&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA9"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data9&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA_VERSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_version&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IS_PRIMARY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;is_primary&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IS_SUPER_PRIMARY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;is_super_primary&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MIMETYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;mimetype&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RAW_CONTACT_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;raw_contact_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC1"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_sync1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC2"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_sync2&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC3"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_sync3&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC4"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_sync4&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
+<interface name="ContactsContract.DataColumnsWithJoins"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="android.provider.BaseColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactOptionsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactStatusColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
+<implements name="android.provider.ContactsContract.RawContactsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.StatusColumns">
+</implements>
+</interface>
 <class name="ContactsContract.Groups"
  extends="java.lang.Object"
  abstract="false"
@@ -114867,6 +115514,10 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.GroupsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.SyncColumns">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -114910,6 +115561,102 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.GroupsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="DELETED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;deleted&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GROUP_VISIBLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;group_visible&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NOTES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;notes&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOULD_SYNC"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;should_sync&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SUMMARY_COUNT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;summ_count&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SUMMARY_WITH_PHONES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;summ_phones&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYSTEM_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;system_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TITLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;title&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.Intents"
  extends="java.lang.Object"
  abstract="false"
@@ -115328,6 +116075,12 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactOptionsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.PhoneLookupColumns">
+</implements>
 <field name="CONTENT_FILTER_URI"
  type="android.net.Uri"
  transient="false"
@@ -115339,6 +116092,47 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.PhoneLookupColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="LABEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;label&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NUMBER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;number&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;type&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.Presence"
  extends="android.provider.ContactsContract.StatusUpdates"
  abstract="false"
@@ -115356,6 +116150,69 @@
 >
 </constructor>
 </class>
+<interface name="ContactsContract.PresenceColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="CUSTOM_PROTOCOL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;custom_protocol&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;presence_data_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IM_ACCOUNT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;im_account&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IM_HANDLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;im_handle&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PROTOCOL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;protocol&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.QuickContact"
  extends="java.lang.Object"
  abstract="false"
@@ -115458,6 +116315,12 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactOptionsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.RawContactsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.SyncColumns">
+</implements>
 <method name="getContactLookupUri"
  return="android.net.Uri"
  abstract="false"
@@ -115560,6 +116423,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
  transient="false"
@@ -115582,6 +116447,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
  transient="false"
@@ -115605,6 +116472,47 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.RawContactsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="AGGREGATION_MODE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;aggregation_mode&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTACT_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DELETED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;deleted&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.RawContactsEntity"
  extends="java.lang.Object"
  abstract="false"
@@ -115615,6 +116523,10 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
+<implements name="android.provider.ContactsContract.RawContactsColumns">
+</implements>
 <field name="CONTENT_TYPE"
  type="java.lang.String"
  transient="false"
@@ -115656,6 +116568,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.SettingsColumns">
+</implements>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -115689,6 +116603,165 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.SettingsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="ACCOUNT_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;account_name&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACCOUNT_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;account_type&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ANY_UNSYNCED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;any_unsynced&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOULD_SYNC"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;should_sync&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNGROUPED_COUNT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;summ_count&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNGROUPED_VISIBLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;ungrouped_visible&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNGROUPED_WITH_PHONES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;summ_phones&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
+<interface name="ContactsContract.StatusColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="PRESENCE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;mode&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;status&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ICON"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;status_icon&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_LABEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;status_label&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_RES_PACKAGE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;status_res_package&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_TIMESTAMP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;status_ts&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.StatusUpdates"
  extends="java.lang.Object"
  abstract="false"
@@ -115697,6 +116770,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.provider.ContactsContract.PresenceColumns">
+</implements>
+<implements name="android.provider.ContactsContract.StatusColumns">
+</implements>
 <method name="getPresenceIconResourceId"
  return="int"
  abstract="false"
@@ -115756,6 +116833,71 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.SyncColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<implements name="android.provider.ContactsContract.BaseSyncColumns">
+</implements>
+<field name="ACCOUNT_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;account_name&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACCOUNT_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;account_type&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DIRTY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;dirty&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOURCE_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sourceid&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VERSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;version&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.SyncState"
  extends="java.lang.Object"
  abstract="false"
@@ -142639,6 +143781,29 @@
 </parameter>
 </method>
 </interface>
+<interface name="LeadingMarginSpan.LeadingMarginSpan2"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.text.style.LeadingMarginSpan">
+</implements>
+<implements name="android.text.style.WrapTogetherSpan">
+</implements>
+<method name="getLeadingMarginLineCount"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
 <class name="LeadingMarginSpan.Standard"
  extends="java.lang.Object"
  abstract="false"
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index b63e97f..6880144 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -309,7 +309,7 @@
             oldClient = mCameraClient;
 
             // did the client actually change?
-            if (client->asBinder() == mCameraClient->asBinder()) {
+            if ((mCameraClient != NULL) && (client->asBinder() == mCameraClient->asBinder())) {
                 LOGD("Connect to the same client");
                 return NO_ERROR;
             }
@@ -878,7 +878,10 @@
         mSurface->unregisterBuffers();
     }
 
-    mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
+    }
     mHardware->disableMsgType(CAMERA_MSG_SHUTTER);
 
     // It takes some time before yuvPicture callback to be called.
@@ -932,31 +935,38 @@
         }
     }
 
-    // Is the callback enabled or not?
-    if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
+    // local copy of the callback flags
+    int flags = mPreviewCallbackFlag;
+
+    // is callback enabled?
+    if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
         // If the enable bit is off, the copy-out and one-shot bits are ignored
         LOGV("frame callback is diabled");
         return;
     }
 
-    // Is the received frame copied out or not?
-    if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
-        LOGV("frame is copied out");
-        copyFrameAndPostCopiedFrame(heap, offset, size);
-    } else {
-        LOGV("frame is directly sent out without copying");
-        mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
-    }
+    // hold a strong pointer to the client
+    sp<ICameraClient> c = mCameraClient;
 
-    // Is this is one-shot only?
-    if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
-        LOGV("One-shot only, thus clear the bits and disable frame callback");
+    // clear callback flags if no client or one-shot mode
+    if ((c == NULL) || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
+        LOGV("Disable preview callback");
         mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
                                 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
                                 FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        // TODO: Shouldn't we use this API for non-overlay hardware as well?
         if (mUseOverlay)
             mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
     }
+
+    // Is the received frame copied out or not?
+    if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+        LOGV("frame is copied");
+        copyFrameAndPostCopiedFrame(c, heap, offset, size);
+    } else {
+        LOGV("frame is forwarded");
+        c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
+    }
 }
 
 // picture callback - postview image ready
@@ -972,7 +982,10 @@
     }
 #endif
 
-    mCameraClient->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
+    }
     mHardware->disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
 }
 
@@ -997,7 +1010,10 @@
         mSurface->postBuffer(offset);
     }
 
-    mCameraClient->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
+    }
     mHardware->disableMsgType(CAMERA_MSG_RAW_IMAGE);
 }
 
@@ -1014,7 +1030,10 @@
     }
 #endif
 
-    mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
+    }
     mHardware->disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
 }
 
@@ -1032,7 +1051,10 @@
             client->handleShutter();
             break;
         default:
-            client->mCameraClient->notifyCallback(msgType, ext1, ext2);
+            sp<ICameraClient> c = client->mCameraClient;
+            if (c != NULL) {
+                c->notifyCallback(msgType, ext1, ext2);
+            }
             break;
     }
 
@@ -1053,10 +1075,13 @@
         return;
     }
 
+    sp<ICameraClient> c = client->mCameraClient;
     if (dataPtr == NULL) {
         LOGE("Null data returned in data callback");
-        client->mCameraClient->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
-        client->mCameraClient->dataCallback(msgType, NULL);
+        if (c != NULL) {
+            c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+            c->dataCallback(msgType, NULL);
+        }
         return;
     }
 
@@ -1074,7 +1099,9 @@
             client->handleCompressedPicture(dataPtr);
             break;
         default:
-            client->mCameraClient->dataCallback(msgType, dataPtr);
+            if (c != NULL) {
+                c->dataCallback(msgType, dataPtr);
+            }
             break;
     }
 
@@ -1095,15 +1122,20 @@
     if (client == 0) {
         return;
     }
+    sp<ICameraClient> c = client->mCameraClient;
 
     if (dataPtr == NULL) {
         LOGE("Null data returned in data with timestamp callback");
-        client->mCameraClient->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
-        client->mCameraClient->dataCallbackTimestamp(0, msgType, NULL);
+        if (c != NULL) {
+            c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+            c->dataCallbackTimestamp(0, msgType, NULL);
+        }
         return;
     }
 
-    client->mCameraClient->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+    if (c != NULL) {
+        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+    }
 
 #if DEBUG_CLIENT_REFERENCES
     if (client->getStrongCount() == 1) {
@@ -1161,7 +1193,8 @@
     return mHardware->sendCommand(cmd, arg1, arg2);
 }
 
-void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
+void CameraService::Client::copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
+        const sp<IMemoryHeap>& heap, size_t offset, size_t size)
 {
     LOGV("copyFrameAndPostCopiedFrame");
     // It is necessary to copy out of pmem before sending this to
@@ -1186,7 +1219,7 @@
         LOGE("failed to allocate space for frame callback");
         return;
     }
-    mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
+    client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
 }
 
 status_t CameraService::dump(int fd, const Vector<String16>& args)
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 2e3597f..2fcf839 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -23,10 +23,9 @@
 #include <ui/CameraHardwareInterface.h>
 #include <ui/Camera.h>
 
-class android::MemoryHeapBase;
-
 namespace android {
 
+class MemoryHeapBase;
 class MediaPlayer;
 
 // ----------------------------------------------------------------------------
@@ -151,7 +150,8 @@
                     void        handleRawPicture(const sp<IMemory>&);
                     void        handleCompressedPicture(const sp<IMemory>&);
 
-                    void        copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size);
+                    void        copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
+                                    const sp<IMemoryHeap>& heap, size_t offset, size_t size);
 
         // camera operation mode
         enum camera_mode {
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 4d4d013..3b7cece 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -52,6 +52,9 @@
 static void playSource(OMXClient *client, const sp<MediaSource> &source) {
     sp<MetaData> meta = source->getFormat();
 
+    int64_t durationUs;
+    CHECK(meta->findInt64(kKeyDuration, &durationUs));
+
     sp<OMXCodec> decoder = OMXCodec::Create(
             client->interface(), meta, false /* createEncoder */, source);
 
@@ -61,7 +64,7 @@
 
     decoder->start();
 
-    if (gReproduceBug == 3) {
+    if (gReproduceBug >= 3 && gReproduceBug <= 5) {
         status_t err;
         MediaBuffer *buffer;
         MediaSource::ReadOptions options;
@@ -85,10 +88,19 @@
                 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
 
                 bool failed = false;
+
                 if (seekTimeUs >= 0) {
                     int64_t diff = timestampUs - seekTimeUs;
 
-                    if (diff > 500000) {
+                    if (diff < 0) {
+                        diff = -diff;
+                    }
+
+                    if ((gReproduceBug == 4 && diff > 500000)
+                        || (gReproduceBug == 5 && timestampUs < 0)) {
+                        printf("wanted: %.2f secs, got: %.2f secs\n",
+                               seekTimeUs / 1E6, timestampUs / 1E6);
+
                         printf("ERROR: ");
                         failed = true;
                     }
@@ -105,13 +117,16 @@
                 }
 
                 shouldSeek = ((double)rand() / RAND_MAX) < 0.1;
-                shouldSeek = false;
+
+                if (gReproduceBug == 3) {
+                    shouldSeek = false;
+                }
             }
 
             seekTimeUs = -1;
 
             if (shouldSeek) {
-                seekTimeUs = (rand() * 30E6) / RAND_MAX;
+                seekTimeUs = (rand() * (float)durationUs) / RAND_MAX;
                 options.setSeekTo(seekTimeUs);
 
                 printf("seeking to %lld us (%.2f secs)\n",
@@ -273,7 +288,7 @@
 
         CHECK(service.get() != NULL);
 
-        sp<IOMX> omx = service->createOMX();
+        sp<IOMX> omx = service->getOMX();
         CHECK(omx.get() != NULL);
 
         const char *kMimeTypes[] = {
@@ -319,11 +334,11 @@
 
         CHECK(service.get() != NULL);
 
-        sp<IOMX> omx = service->createOMX();
+        sp<IOMX> omx = service->getOMX();
         CHECK(omx.get() != NULL);
 
         List<String8> list;
-        omx->list_nodes(&list);
+        omx->listNodes(&list);
 
         for (List<String8>::iterator it = list.begin();
              it != list.end(); ++it) {
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 3a11cb3..be74073 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.ServiceConnection;
+import android.content.ComponentName;
 import android.content.pm.PackageManager;
 import android.content.pm.RegisteredServicesCache;
 import android.content.pm.PackageInfo;
@@ -90,11 +92,8 @@
 
     // Messages that can be sent on mHandler
     private static final int MESSAGE_TIMED_OUT = 3;
-    private static final int MESSAGE_CONNECTED = 7;
-    private static final int MESSAGE_DISCONNECTED = 8;
 
     private final AccountAuthenticatorCache mAuthenticatorCache;
-    private final AuthenticatorBindHelper mBindHelper;
     private final DatabaseHelper mOpenHelper;
     private final SimWatcher mSimWatcher;
 
@@ -220,10 +219,12 @@
 
         mAuthenticatorCache = new AccountAuthenticatorCache(mContext);
         mAuthenticatorCache.setListener(this);
-        mBindHelper = new AuthenticatorBindHelper(mContext, mAuthenticatorCache, mMessageHandler,
-                MESSAGE_CONNECTED, MESSAGE_DISCONNECTED);
 
-        mSimWatcher = new SimWatcher(mContext);
+        if (SystemProperties.getBoolean("ro.config.sim_password_clear", false)) {
+          mSimWatcher = new SimWatcher(mContext);
+        } else {
+          mSimWatcher = null;
+        }
         sThis.set(this);
 
         onRegisteredServicesCacheChanged();
@@ -1068,7 +1069,7 @@
     }
 
     private abstract class Session extends IAccountAuthenticatorResponse.Stub
-            implements AuthenticatorBindHelper.Callback, IBinder.DeathRecipient {
+            implements IBinder.DeathRecipient, ServiceConnection {
         IAccountManagerResponse mResponse;
         final String mAccountType;
         final boolean mExpectActivityLaunch;
@@ -1150,7 +1151,7 @@
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.v(TAG, "initiating bind to authenticator type " + mAccountType);
             }
-            if (!mBindHelper.bind(mAccountType, this)) {
+            if (!bindToAuthenticator(mAccountType)) {
                 Log.d(TAG, "bind attempt failed for " + toDebugString());
                 onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "bind failure");
             }
@@ -1159,7 +1160,7 @@
         private void unbind() {
             if (mAuthenticator != null) {
                 mAuthenticator = null;
-                mBindHelper.unbind(this);
+                mContext.unbindService(this);
             }
         }
 
@@ -1172,7 +1173,7 @@
             mMessageHandler.removeMessages(MESSAGE_TIMED_OUT, this);
         }
 
-        public void onConnected(IBinder service) {
+        public void onServiceConnected(ComponentName name, IBinder service) {
             mAuthenticator = IAccountAuthenticator.Stub.asInterface(service);
             try {
                 run();
@@ -1182,9 +1183,7 @@
             }
         }
 
-        public abstract void run() throws RemoteException;
-
-        public void onDisconnected() {
+        public void onServiceDisconnected(ComponentName name) {
             mAuthenticator = null;
             IAccountManagerResponse response = getResponseAndClose();
             if (response != null) {
@@ -1193,6 +1192,8 @@
             }
         }
 
+        public abstract void run() throws RemoteException;
+
         public void onTimedOut() {
             IAccountManagerResponse response = getResponseAndClose();
             if (response != null) {
@@ -1262,6 +1263,39 @@
                 }
             }
         }
+
+        /**
+         * find the component name for the authenticator and initiate a bind
+         * if no authenticator or the bind fails then return false, otherwise return true
+         */
+        private boolean bindToAuthenticator(String authenticatorType) {
+            AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
+                    mAuthenticatorCache.getServiceInfo(
+                            AuthenticatorDescription.newKey(authenticatorType));
+            if (authenticatorInfo == null) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "there is no authenticator for " + authenticatorType
+                            + ", bailing out");
+                }
+                return false;
+            }
+
+            Intent intent = new Intent();
+            intent.setAction(AccountManager.ACTION_AUTHENTICATOR_INTENT);
+            intent.setComponent(authenticatorInfo.componentName);
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName);
+            }
+            if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
+                }
+                return false;
+            }
+
+
+            return true;
+        }
     }
 
     private class MessageHandler extends Handler {
@@ -1270,9 +1304,6 @@
         }
 
         public void handleMessage(Message msg) {
-            if (mBindHelper.handleMessage(msg)) {
-                return;
-            }
             switch (msg.what) {
                 case MESSAGE_TIMED_OUT:
                     Session session = (Session)msg.obj;
@@ -1567,13 +1598,14 @@
     private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
         final boolean fromAuthenticator = hasAuthenticatorUid(account.type, callerUid);
         final boolean hasExplicitGrants = hasExplicitlyGrantedPermission(account, authTokenType);
+        final boolean inSystemImage = inSystemImage(callerUid);
         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 || inSystemImage(callerUid);
+        return fromAuthenticator || hasExplicitGrants || inSystemImage;
     }
 
     private boolean hasAuthenticatorUid(String accountType, int callingUid) {
diff --git a/core/java/android/accounts/AuthenticatorBindHelper.java b/core/java/android/accounts/AuthenticatorBindHelper.java
deleted file mode 100644
index 2ca1f0e..0000000
--- a/core/java/android/accounts/AuthenticatorBindHelper.java
+++ /dev/null
@@ -1,258 +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 android.accounts;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Map;
-
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
-/**
- * A helper object that simplifies binding to Account Authenticators. It uses the
- * {@link AccountAuthenticatorCache} to find the component name of the authenticators,
- * allowing the user to bind by account name. It also allows multiple, simultaneous binds
- * to the same authenticator, with each bind call guaranteed to return either
- * {@link Callback#onConnected} or {@link Callback#onDisconnected} if the bind() call
- * itself succeeds, even if the authenticator is already bound internally.
- * @hide
- */
-public class AuthenticatorBindHelper {
-    private static final String TAG = "Accounts";
-    private final Handler mHandler;
-    private final Context mContext;
-    private final int mMessageWhatConnected;
-    private final int mMessageWhatDisconnected;
-    private final Map<String, MyServiceConnection> mServiceConnections = Maps.newHashMap();
-    private final Map<String, ArrayList<Callback>> mServiceUsers = Maps.newHashMap();
-    private final AccountAuthenticatorCache mAuthenticatorCache;
-
-    public AuthenticatorBindHelper(Context context,
-            AccountAuthenticatorCache authenticatorCache, Handler handler,
-            int messageWhatConnected, int messageWhatDisconnected) {
-        mContext = context;
-        mHandler = handler;
-        mAuthenticatorCache = authenticatorCache;
-        mMessageWhatConnected = messageWhatConnected;
-        mMessageWhatDisconnected = messageWhatDisconnected;
-    }
-
-    public interface Callback {
-        void onConnected(IBinder service);
-        void onDisconnected();
-    }
-
-    public boolean bind(String authenticatorType, Callback callback) {
-        // if the authenticator is connecting or connected then return true
-        synchronized (mServiceConnections) {
-            if (mServiceConnections.containsKey(authenticatorType)) {
-                MyServiceConnection connection = mServiceConnections.get(authenticatorType);
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "service connection already exists for " + authenticatorType);
-                }
-                mServiceUsers.get(authenticatorType).add(callback);
-                if (connection.mService != null) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "the service is connected, scheduling a connected message for "
-                                + authenticatorType);
-                    }
-                    connection.scheduleCallbackConnectedMessage(callback);
-                } else {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "the service is *not* connected, waiting for for "
-                                + authenticatorType);
-                    }
-                }
-                return true;
-            }
-
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "there is no service connection for " + authenticatorType);
-            }
-
-            // otherwise find the component name for the authenticator and initiate a bind
-            // if no authenticator or the bind fails then return false, otherwise return true
-            AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
-                    mAuthenticatorCache.getServiceInfo(
-                            AuthenticatorDescription.newKey(authenticatorType));
-            if (authenticatorInfo == null) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "there is no authenticator for " + authenticatorType
-                            + ", bailing out");
-                }
-                return false;
-            }
-
-            MyServiceConnection connection = new MyServiceConnection(authenticatorType);
-
-            Intent intent = new Intent();
-            intent.setAction("android.accounts.AccountAuthenticator");
-            intent.setComponent(authenticatorInfo.componentName);
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName);
-            }
-            if (!mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
-                }
-                return false;
-            }
-
-            mServiceConnections.put(authenticatorType, connection);
-            mServiceUsers.put(authenticatorType, Lists.newArrayList(callback));
-            return true;
-        }
-    }
-
-    public void unbind(Callback callbackToUnbind) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "unbinding callback " + callbackToUnbind);
-        }
-        synchronized (mServiceConnections) {
-            for (Map.Entry<String, ArrayList<Callback>> entry : mServiceUsers.entrySet()) {
-                final String authenticatorType = entry.getKey();
-                final ArrayList<Callback> serviceUsers = entry.getValue();
-                for (Callback callback : serviceUsers) {
-                    if (callback == callbackToUnbind) {
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "found callback in service" + authenticatorType);
-                        }
-                        serviceUsers.remove(callbackToUnbind);
-                        if (serviceUsers.isEmpty()) {
-                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                                Log.v(TAG, "there are no more callbacks for service "
-                                        + authenticatorType + ", unbinding service");
-                            }
-                            unbindFromServiceLocked(authenticatorType);
-                        } else {
-                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                                Log.v(TAG, "leaving service " + authenticatorType
-                                        + " around since there are still callbacks using it");
-                            }
-                        }
-                        return;
-                    }
-                }
-            }
-            Log.e(TAG, "did not find callback " + callbackToUnbind + " in any of the services");
-        }
-    }
-
-    /**
-     * You must synchronized on mServiceConnections before calling this
-     */
-    private void unbindFromServiceLocked(String authenticatorType) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "unbindService from " + authenticatorType);
-        }
-        mContext.unbindService(mServiceConnections.get(authenticatorType));
-        mServiceUsers.remove(authenticatorType);
-        mServiceConnections.remove(authenticatorType);
-    }
-
-    private class ConnectedMessagePayload {
-        public final IBinder mService;
-        public final Callback mCallback;
-        public ConnectedMessagePayload(IBinder service, Callback callback) {
-            mService = service;
-            mCallback = callback;
-        }
-    }
-
-    private class MyServiceConnection implements ServiceConnection {
-        private final String mAuthenticatorType;
-        private IBinder mService = null;
-
-        public MyServiceConnection(String authenticatorType) {
-            mAuthenticatorType = authenticatorType;
-        }
-
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "onServiceConnected for account type " + mAuthenticatorType);
-            }
-            // post a message for each service user to tell them that the service is connected
-            synchronized (mServiceConnections) {
-                mService = service;
-                for (Callback callback : mServiceUsers.get(mAuthenticatorType)) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "the service became connected, scheduling a connected "
-                                + "message for " + mAuthenticatorType);
-                    }
-                    scheduleCallbackConnectedMessage(callback);
-                }
-            }
-        }
-
-        private void scheduleCallbackConnectedMessage(Callback callback) {
-            final ConnectedMessagePayload payload =
-                    new ConnectedMessagePayload(mService, callback);
-            mHandler.obtainMessage(mMessageWhatConnected, payload).sendToTarget();
-        }
-
-        public void onServiceDisconnected(ComponentName name) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "onServiceDisconnected for account type " + mAuthenticatorType);
-            }
-            // post a message for each service user to tell them that the service is disconnected,
-            // and unbind from the service.
-            synchronized (mServiceConnections) {
-                final ArrayList<Callback> callbackList = mServiceUsers.get(mAuthenticatorType);
-                if (callbackList != null) {
-                    for (Callback callback : callbackList) {
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "the service became disconnected, scheduling a "
-                                    + "disconnected message for "
-                                    + mAuthenticatorType);
-                        }
-                        mHandler.obtainMessage(mMessageWhatDisconnected, callback).sendToTarget();
-                    }
-                    unbindFromServiceLocked(mAuthenticatorType);
-                }
-            }
-        }
-    }
-
-    boolean handleMessage(Message message) {
-        if (message.what == mMessageWhatConnected) {
-            ConnectedMessagePayload payload = (ConnectedMessagePayload)message.obj;
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "notifying callback " + payload.mCallback + " that it is connected");
-            }
-            payload.mCallback.onConnected(payload.mService);
-            return true;
-        } else if (message.what == mMessageWhatDisconnected) {
-            Callback callback = (Callback)message.obj;
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "notifying callback " + callback + " that it is disconnected");
-            }
-            callback.onDisconnected();
-            return true;
-        } else {
-            return false;
-        }
-    }
-}
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
index e3ed2e9..f4b7258 100644
--- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -18,14 +18,16 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.widget.TextView;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
+import android.widget.LinearLayout;
+import android.widget.ImageView;
 import android.view.View;
 import android.view.LayoutInflater;
-import android.view.ViewGroup;
+import android.view.Window;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.text.TextUtils;
+import android.graphics.drawable.Drawable;
 import com.android.internal.R;
 
 /**
@@ -43,62 +45,68 @@
     private String mAuthTokenType;
     private int mUid;
     private Bundle mResultBundle = null;
+    protected LayoutInflater mInflater;
 
     protected void onCreate(Bundle savedInstanceState) {
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
         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);
+        setContentView(R.layout.grant_credentials_permission);
 
-        findViewById(R.id.allow).setOnClickListener(this);
-        findViewById(R.id.deny).setOnClickListener(this);
+        mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
-        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.name, accountTypeLabel));
-        } else {
-            CharSequence grantCredentialsPermissionFormat = getResources().getText(
-                    R.string.grant_credentials_permission_message_with_authtokenlabel_desc);
-            messageView.setText(String.format(grantCredentialsPermissionFormat.toString(),
-                    authTokenLabel, mAccount.name, accountTypeLabel));
-        }
+        final Bundle extras = getIntent().getExtras();
+        mAccount = extras.getParcelable(EXTRAS_ACCOUNT);
+        mAuthTokenType = extras.getString(EXTRAS_AUTH_TOKEN_TYPE);
+        mUid = extras.getInt(EXTRAS_REQUESTING_UID);
+        final String accountTypeLabel = extras.getString(EXTRAS_ACCOUNT_TYPE_LABEL);
+        final String[] packages = extras.getStringArray(EXTRAS_PACKAGES);
+        final String authTokenLabel = extras.getString(EXTRAS_AUTH_TOKEN_LABEL);
 
-        String[] packageLabels = new String[packages.length];
+        findViewById(R.id.allow_button).setOnClickListener(this);
+        findViewById(R.id.deny_button).setOnClickListener(this);
+
+        LinearLayout packagesListView = (LinearLayout) findViewById(R.id.packages_list);
+
         final PackageManager pm = getPackageManager();
-        for (int i = 0; i < packages.length; i++) {
+        for (String pkg : packages) {
+            String packageLabel;
             try {
-                packageLabels[i] =
-                        pm.getApplicationLabel(pm.getApplicationInfo(packages[i], 0)).toString();
+                packageLabel = pm.getApplicationLabel(pm.getApplicationInfo(pkg, 0)).toString();
             } catch (PackageManager.NameNotFoundException e) {
-                packageLabels[i] = packages[i];
+                packageLabel = pkg;
             }
+            packagesListView.addView(newPackageView(packageLabel));
         }
-        ((ListView) findViewById(R.id.packages_list)).setAdapter(
-                new PackagesArrayAdapter(this, packageLabels));
+
+        ((TextView) findViewById(R.id.account_name)).setText(mAccount.name);
+        ((TextView) findViewById(R.id.account_type)).setText(accountTypeLabel);
+        TextView authTokenTypeView = (TextView) findViewById(R.id.authtoken_type);
+        if (TextUtils.isEmpty(authTokenLabel)) {
+            authTokenTypeView.setVisibility(View.GONE);
+        } else {
+            authTokenTypeView.setText(authTokenLabel);
+        }
+    }
+
+    private View newPackageView(String packageLabel) {
+        View view = mInflater.inflate(R.layout.permissions_package_list_item, null);
+        ((TextView) view.findViewById(R.id.package_label)).setText(packageLabel);
+        return view;
     }
 
     public void onClick(View v) {
+        final AccountManagerService accountManagerService = AccountManagerService.getSingleton();
         switch (v.getId()) {
-            case R.id.allow:
-                AccountManagerService.getSingleton().grantAppPermission(mAccount, mAuthTokenType,
-                        mUid);
+            case R.id.allow_button:
+                accountManagerService.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);
+            case R.id.deny_button:
+                accountManagerService.revokeAppPermission(mAccount, mAuthTokenType, mUid);
                 setResult(RESULT_CANCELED);
                 break;
         }
@@ -110,63 +118,20 @@
     }
 
     /**
-     * Sends the result or a Constants.ERROR_CODE_CANCELED error if a result isn't present.
+     * Sends the result or a {@link AccountManager#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) {
+        AccountAuthenticatorResponse response = intent.getParcelableExtra(EXTRAS_RESPONSE);
+        if (response != null) {
             // send the result bundle back if set, otherwise send an error.
             if (mResultBundle != null) {
-                accountAuthenticatorResponse.onResult(mResultBundle);
+                response.onResult(mResultBundle);
             } else {
-                accountAuthenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
+                response.onError(AccountManager.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/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index a4c141e..bb0cbe9 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -123,7 +123,8 @@
 
     @Override
     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
-        final ParcelableSparseArray jail = (ParcelableSparseArray) container.get(generateId());
+        ParcelableSparseArray jail = (ParcelableSparseArray) container.get(generateId());
+        if (jail == null) jail = new ParcelableSparseArray();
         super.dispatchRestoreInstanceState(jail);
     }
 
diff --git a/core/java/android/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java
index eba8715..9866862 100644
--- a/core/java/android/content/AbstractSyncableContentProvider.java
+++ b/core/java/android/content/AbstractSyncableContentProvider.java
@@ -747,4 +747,8 @@
     public void writeSyncDataBytes(Account account, byte[] data) {
         mSyncState.writeSyncDataBytes(mOpenHelper.getWritableDatabase(), account, data);
     }
+
+    protected ContentProvider getSyncStateProvider() {
+        return mSyncState.asContentProvider();
+    }
 }
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index fb6091a..0db6155 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -21,6 +21,7 @@
 import android.os.Process;
 import android.os.NetStat;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.util.EventLog;
 
 import java.util.concurrent.atomic.AtomicInteger;
@@ -117,6 +118,12 @@
                 }
             }
         }
+
+        public void initialize(Account account, String authority) throws RemoteException {
+            Bundle extras = new Bundle();
+            extras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
+            startSync(null, authority, account, extras);
+        }
     }
 
     /**
diff --git a/core/java/android/content/ISyncAdapter.aidl b/core/java/android/content/ISyncAdapter.aidl
index 4660527..dd9d14e 100644
--- a/core/java/android/content/ISyncAdapter.aidl
+++ b/core/java/android/content/ISyncAdapter.aidl
@@ -44,4 +44,12 @@
      * @param syncContext the ISyncContext that was passed to {@link #startSync}
      */
     void cancelSync(ISyncContext syncContext);
+
+    /**
+     * Initialize the SyncAdapter for this account and authority.
+     *
+     * @param account the account that should be synced
+     * @param authority the authority that should be synced
+     */
+    void initialize(in Account account, String authority);
 }
diff --git a/core/java/android/content/SyncAdapter.java b/core/java/android/content/SyncAdapter.java
index 88dc332..af1634e 100644
--- a/core/java/android/content/SyncAdapter.java
+++ b/core/java/android/content/SyncAdapter.java
@@ -38,6 +38,12 @@
         public void cancelSync(ISyncContext syncContext) throws RemoteException {
             SyncAdapter.this.cancelSync();
         }
+
+        public void initialize(Account account, String authority) throws RemoteException {
+            Bundle extras = new Bundle();
+            extras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
+            startSync(null, authority, account, extras);
+        }
     }
 
     Transport mTransport = new Transport();
diff --git a/core/java/android/content/SyncContext.java b/core/java/android/content/SyncContext.java
index 587586d..cc914c0 100644
--- a/core/java/android/content/SyncContext.java
+++ b/core/java/android/content/SyncContext.java
@@ -56,7 +56,9 @@
         if (now < mLastHeartbeatSendTime + HEARTBEAT_SEND_INTERVAL_IN_MS) return;
         try {
             mLastHeartbeatSendTime = now;
-            mSyncContext.sendHeartbeat();
+            if (mSyncContext != null) {
+                mSyncContext.sendHeartbeat();
+            }
         } catch (RemoteException e) {
             // this should never happen
         }
@@ -64,13 +66,15 @@
 
     public void onFinished(SyncResult result) {
         try {
-            mSyncContext.onFinished(result);
+            if (mSyncContext != null) {
+                mSyncContext.onFinished(result);
+            }
         } catch (RemoteException e) {
             // this should never happen
         }
     }
 
     public IBinder getSyncContextBinder() {
-        return mSyncContext.asBinder();
+        return (mSyncContext == null) ? null : mSyncContext.asBinder();
     }
 }
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 9757ef6..8a529e9 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -544,6 +544,46 @@
         return (activeSyncContext != null) ? activeSyncContext.mSyncOperation.account : null;
     }
 
+    private void initializeSyncAdapter(Account account, String authority) {
+        SyncAdapterType syncAdapterType = SyncAdapterType.newKey(authority, account.type);
+        RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
+                mSyncAdapters.getServiceInfo(syncAdapterType);
+        if (syncAdapterInfo == null) {
+            Log.w(TAG, "can't find a sync adapter for " + syncAdapterType);
+            return;
+        }
+
+        Intent intent = new Intent();
+        intent.setAction("android.content.SyncAdapter");
+        intent.setComponent(syncAdapterInfo.componentName);
+        mContext.bindService(intent, new InitializerServiceConnection(account, authority),
+                Context.BIND_AUTO_CREATE);
+    }
+
+    private class InitializerServiceConnection implements ServiceConnection {
+        private final Account mAccount;
+        private final String mAuthority;
+
+        public InitializerServiceConnection(Account account, String authority) {
+            mAccount = account;
+            mAuthority = authority;
+        }
+
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            try {
+                ISyncAdapter.Stub.asInterface(service).initialize(mAccount, mAuthority);
+            } catch (RemoteException e) {
+                // doesn't matter, we will retry again later
+            } finally {
+                mContext.unbindService(this);
+            }
+        }
+
+        public void onServiceDisconnected(ComponentName name) {
+            mContext.unbindService(this);
+        }
+    }
+
     /**
      * Returns whether or not sync is enabled.  Sync can be enabled by
      * setting the system property "ro.config.sync" to the value "yes".
@@ -686,36 +726,34 @@
                         continue;
                     }
 
-                    // make this an initialization sync if the isSyncable state is unknown
-                    Bundle extrasCopy = extras;
-                    long delayCopy = delay;
+                    // initialize the SyncAdapter if the isSyncable state is unknown
                     if (isSyncable < 0) {
-                        extrasCopy = new Bundle(extras);
-                        extrasCopy.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
-                        delayCopy = -1; // expedite this
-                    } else {
-                        final boolean syncAutomatically = masterSyncAutomatically
-                                && mSyncStorageEngine.getSyncAutomatically(account, authority);
-                        boolean syncAllowed =
-                                manualSync || (backgroundDataUsageAllowed && syncAutomatically);
-                        if (!syncAllowed) {
-                            if (isLoggable) {
-                                Log.d(TAG, "scheduleSync: sync of " + account + ", " + authority
-                                        + " is not allowed, dropping request");
-                            }
-                            continue;
-                        }
+                        initializeSyncAdapter(account, authority);
+                        continue;
                     }
+
+                    final boolean syncAutomatically = masterSyncAutomatically
+                            && mSyncStorageEngine.getSyncAutomatically(account, authority);
+                    boolean syncAllowed =
+                            manualSync || (backgroundDataUsageAllowed && syncAutomatically);
+                    if (!syncAllowed) {
+                        if (isLoggable) {
+                            Log.d(TAG, "scheduleSync: sync of " + account + ", " + authority
+                                    + " is not allowed, dropping request");
+                        }
+                        continue;
+                    }
+
                     if (isLoggable) {
                         Log.v(TAG, "scheduleSync:"
-                                + " delay " + delayCopy
+                                + " delay " + delay
                                 + ", source " + source
                                 + ", account " + account
                                 + ", authority " + authority
-                                + ", extras " + extrasCopy);
+                                + ", extras " + extras);
                     }
                     scheduleSyncOperation(
-                            new SyncOperation(account, source, authority, extrasCopy, delayCopy));
+                            new SyncOperation(account, source, authority, extras, delay));
                 }
             }
         }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index a49a27a0..b706c5c 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -130,6 +130,7 @@
     private static final String MISC_DATA = "m";
     private static final String SCREEN_BRIGHTNESS_DATA = "br";
     private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
+    private static final String SIGNAL_SCANNING_TIME_DATA = "sst";
     private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc";
     private static final String DATA_CONNECTION_TIME_DATA = "dct";
     private static final String DATA_CONNECTION_COUNT_DATA = "dcc";
@@ -440,6 +441,15 @@
             long batteryRealtime, int which);
 
     /**
+     * Returns the time in microseconds that the phone has been trying to
+     * acquire a signal.
+     *
+     * {@hide}
+     */
+    public abstract long getPhoneSignalScanningTime(
+            long batteryRealtime, int which);
+
+    /**
      * Returns the number of times the phone has entered the given signal strength.
      * 
      * {@hide}
@@ -823,6 +833,8 @@
             args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
         }
         dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
+        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
+                getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
             args[i] = getPhoneSignalStrengthCount(i, which);
         }
@@ -1130,7 +1142,13 @@
         }
         if (!didOne) sb.append("No activity");
         pw.println(sb.toString());
-        
+
+        sb.setLength(0);
+        sb.append(prefix);
+        sb.append("  Signal scanning time: ");
+        formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
+        pw.println(sb.toString());
+
         sb.setLength(0);
         sb.append(prefix);
         sb.append("  Radio types: ");
diff --git a/core/java/android/os/DropBoxEntry.aidl b/core/java/android/os/DropBoxEntry.aidl
new file mode 100644
index 0000000..225eee1
--- /dev/null
+++ b/core/java/android/os/DropBoxEntry.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.os;
+
+parcelable DropBoxEntry;
diff --git a/core/java/android/os/DropBoxEntry.java b/core/java/android/os/DropBoxEntry.java
new file mode 100644
index 0000000..e3816a8
--- /dev/null
+++ b/core/java/android/os/DropBoxEntry.java
@@ -0,0 +1,163 @@
+/*
+ * 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.os;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * A single entry retrieved from an {@link IDropBox} implementation.
+ * This may include a reference to a stream, so you must call
+ * {@link #close()} when you are done using it.
+ *
+ * {@pending}
+ */
+public class DropBoxEntry implements Parcelable {
+    private final String mTag;
+    private final long mTimeMillis;
+
+    private final String mText;
+    private final ParcelFileDescriptor mFileDescriptor;
+    private final int mFlags;
+
+    /** Flag value: Entry's content was deleted to save space. */
+    public static final int IS_EMPTY = 1;
+
+    /** Flag value: Content is human-readable UTF-8 text (possibly compressed). */
+    public static final int IS_TEXT = 2;
+
+    /** Flag value: Content can been decompressed with {@link GZIPOutputStream}. */
+    public static final int IS_GZIPPED = 4;
+
+    /** Create a new DropBoxEntry with the specified contents. */
+    public DropBoxEntry(String tag, long timeMillis, String text) {
+        if (tag == null || text == null) throw new NullPointerException();
+        mTag = tag;
+        mTimeMillis = timeMillis;
+        mText = text;
+        mFileDescriptor = null;
+        mFlags = IS_TEXT;
+    }
+
+    /** Create a new DropBoxEntry with the specified contents. */
+    public DropBoxEntry(String tag, long millis, File data, int flags) throws IOException {
+        if (tag == null) throw new NullPointerException();
+        if (((flags & IS_EMPTY) != 0) != (data == null)) throw new IllegalArgumentException();
+
+        mTag = tag;
+        mTimeMillis = millis;
+        mText = null;
+        mFlags = flags;
+        mFileDescriptor = data == null ? null :
+                ParcelFileDescriptor.open(data, ParcelFileDescriptor.MODE_READ_ONLY);
+    }
+
+    /** Internal constructor for CREATOR.createFromParcel(). */
+    private DropBoxEntry(String tag, long millis, Object value, int flags) {
+        if (tag == null) throw new NullPointerException();
+        if (((flags & IS_EMPTY) != 0) != (value == null)) throw new IllegalArgumentException();
+
+        mTag = tag;
+        mTimeMillis = millis;
+        mFlags = flags;
+
+        if (value == null) {
+            mText = null;
+            mFileDescriptor = null;
+        } else if (value instanceof String) {
+            if ((flags & IS_TEXT) == 0) throw new IllegalArgumentException();
+            mText = (String) value;
+            mFileDescriptor = null;
+        } else if (value instanceof ParcelFileDescriptor) {
+            mText = null;
+            mFileDescriptor = (ParcelFileDescriptor) value;
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    /** Close the input stream associated with this entry. */
+    public synchronized void close() {
+        try { if (mFileDescriptor != null) mFileDescriptor.close(); } catch (IOException e) { }
+    }
+
+    /** @return the tag originally attached to the entry. */
+    public String getTag() { return mTag; }
+
+    /** @return time when the entry was originally created. */
+    public long getTimeMillis() { return mTimeMillis; }
+
+    /** @return flags describing the content returned by @{link #getInputStream()}. */
+    public int getFlags() { return mFlags & ~IS_GZIPPED; }  // getInputStream() decompresses.
+
+    /**
+     * @param maxLength of string to return (will truncate at this length).
+     * @return the uncompressed text contents of the entry, null if the entry is not text.
+     */
+    public String getText(int maxLength) {
+        if (mText != null) return mText.substring(0, Math.min(maxLength, mText.length()));
+        if ((mFlags & IS_TEXT) == 0) return null;
+
+        try {
+            InputStream stream = getInputStream();
+            if (stream == null) return null;
+            char[] buf = new char[maxLength];
+            InputStreamReader reader = new InputStreamReader(stream);
+            return new String(buf, 0, Math.max(0, reader.read(buf)));
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+    /** @return the uncompressed contents of the entry, or null if the contents were lost */
+    public InputStream getInputStream() throws IOException {
+        if (mText != null) return new ByteArrayInputStream(mText.getBytes("UTF8"));
+        if (mFileDescriptor == null) return null;
+        InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(mFileDescriptor);
+        return (mFlags & IS_GZIPPED) != 0 ? new GZIPInputStream(is) : is;
+    }
+
+    public static final Parcelable.Creator<DropBoxEntry> CREATOR = new Parcelable.Creator() {
+        public DropBoxEntry[] newArray(int size) { return new DropBoxEntry[size]; }
+        public DropBoxEntry createFromParcel(Parcel in) {
+            return new DropBoxEntry(
+                    in.readString(), in.readLong(), in.readValue(null), in.readInt());
+        }
+    };
+
+    public int describeContents() {
+        return mFileDescriptor != null ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mTag);
+        out.writeLong(mTimeMillis);
+        if (mFileDescriptor != null) {
+            out.writeValue(mFileDescriptor);
+        } else {
+            out.writeValue(mText);
+        }
+        out.writeInt(mFlags);
+    }
+}
diff --git a/core/java/android/os/IDropBox.aidl b/core/java/android/os/IDropBox.aidl
new file mode 100644
index 0000000..f951e52
--- /dev/null
+++ b/core/java/android/os/IDropBox.aidl
@@ -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.
+ */
+
+package android.os;
+
+import android.os.DropBoxEntry;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Enqueues chunks of data (from various sources -- application crashes, kernel
+ * log records, etc.).  The queue is size bounded and will drop old data if the
+ * enqueued data exceeds the maximum size.
+ *
+ * <p>This interface is implemented by a system service you can access:
+ *
+ * <pre>IDropBox.Stub.asInterface(ServiceManager.getService("dropbox"));</pre>
+ *
+ * <p>Other system services and debugging tools may scan the drop box to upload
+ * entries for processing.
+ *
+ * {@pending}
+ */
+interface IDropBox {
+    /**
+     * Stores human-readable text.  The data may be discarded eventually (or even
+     * immediately) if space is limited, or ignored entirely if the tag has been
+     * blocked (see {@link #isTagEnabled}).
+     *
+     * @param tag describing the type of entry being stored
+     * @param data value to store
+     */
+    void addText(String tag, String data);
+
+    /**
+     * Stores binary data.  The data may be ignored or discarded as with
+     * {@link #addText}.
+     *
+     * @param tag describing the type of entry being stored
+     * @param data value to store
+     * @param flags describing the data, defined in {@link DropBoxEntry}
+     */
+    void addData(String tag, in byte[] data, int flags);
+
+    /**
+     * Stores data read from a file descriptor.  The data may be ignored or
+     * discarded as with {@link #addText}.  You must close your
+     * ParcelFileDescriptor object after calling this method!
+     *
+     * @param tag describing the type of entry being stored
+     * @param data file descriptor to read from
+     * @param flags describing the data, defined in {@link DropBoxEntry}
+     */
+    void addFile(String tag, in ParcelFileDescriptor data, int flags);
+
+    /**
+     * Checks any blacklists (set in system settings) to see whether a certain
+     * tag is allowed.  Entries with disabled tags will be dropped immediately,
+     * so you can save the work of actually constructing and sending the data.
+     *
+     * @param tag that would be used in {@link #addText} or {@link #addFile}
+     * @return whether events with that tag would be accepted
+     */
+    boolean isTagEnabled(String tag);
+
+    /**
+     * Gets the next entry from the drop box *after* the specified time.
+     * Requires android.permission.READ_LOGS.
+     *
+     * @param millis time of the last entry seen
+     * @return the next entry, or null if there are no more entries
+     */
+    DropBoxEntry getNextEntry(long millis);
+
+    // TODO: It may be useful to have some sort of notification mechanism
+    // when data is added to the dropbox, for demand-driven readers --
+    // for now readers need to poll the dropbox to find new data.
+}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 189335e..5ac543d 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -34,7 +34,4 @@
 
     // sets the brightness of the backlights (screen, keyboard, button) 0-255
     void setBacklightBrightness(int brightness);
-
-    // enables or disables automatic brightness mode
-    void setAutoBrightness(boolean on);
 }
diff --git a/core/java/android/pim/vcard/Constants.java b/core/java/android/pim/vcard/Constants.java
index aaa7215..a1c7e10 100644
--- a/core/java/android/pim/vcard/Constants.java
+++ b/core/java/android/pim/vcard/Constants.java
@@ -56,7 +56,7 @@
     public static final String PROPERTY_X_PHONETIC_MIDDLE_NAME = "X-PHONETIC-MIDDLE-NAME";
     public static final String PROPERTY_X_PHONETIC_LAST_NAME = "X-PHONETIC-LAST-NAME";
 
-    // Properties both the current (as of 2009-08-17) ContactsStruct and de-fact vCard extensions
+    // Properties both ContactsStruct in Eclair and de-fact vCard extensions
     // shown in http://en.wikipedia.org/wiki/VCard support are defined here.
     public static final String PROPERTY_X_AIM = "X-AIM";
     public static final String PROPERTY_X_MSN = "X-MSN";
@@ -65,15 +65,12 @@
     public static final String PROPERTY_X_JABBER = "X-JABBER";
     public static final String PROPERTY_X_GOOGLE_TALK = "X-GOOGLE-TALK";
     public static final String PROPERTY_X_SKYPE_USERNAME = "X-SKYPE-USERNAME";
+    // Properties only ContactsStruct has. We alse use this.
+    public static final String PROPERTY_X_QQ = "X-QQ";
+    public static final String PROPERTY_X_NETMEETING = "X-NETMEETING";
+
     // Phone number for Skype, available as usual phone.
     public static final String PROPERTY_X_SKYPE_PSTNNUMBER = "X-SKYPE-PSTNNUMBER";
-    // Some device emits this "X-" attribute, which is specifically invalid but should be
-    // always properly accepted, and emitted in some special case (for that device/application).
-    public static final String PROPERTY_X_GOOGLE_TALK_WITH_SPACE = "X-GOOGLE TALK";
-
-    // Android specific properties
-    // Use only in vCard paser code.
-    public static final String PROPERTY_X_NICKNAME = "X-NICKNAME";
 
     // Properties for DoCoMo vCard.
     public static final String PROPERTY_X_CLASS = "X-CLASS";
@@ -81,6 +78,11 @@
     public static final String PROPERTY_X_NO = "X-NO";
     public static final String PROPERTY_X_DCM_HMN_MODE = "X-DCM-HMN-MODE";
 
+    // For some historical reason, we often use the term "ATTR"/"attribute" especially toward
+    // what is called "param" in both vCard specs, while vCard, while vCard importer side uses
+    // "param".
+    //
+    // TODO: Confusing. Fix it.
     public static final String ATTR_TYPE = "TYPE";
 
     // How more than one TYPE fields are expressed is different between vCard 2.1 and vCard 3.0
@@ -102,13 +104,19 @@
     public static final String ATTR_TYPE_VOICE = "VOICE";
     public static final String ATTR_TYPE_INTERNET = "INTERNET";
 
-    // Abbreviation of "preferable"? We interpret this value as "primary" property.
+    // Abbreviation of "prefered" according to vCard 2.1 specification.
+    // We interpret this value as "primary" property during import/export.
+    //
+    // Note: Both vCard specs does anything about the requirement about this attribute,
+    //       but there may be some vCard importer which will get confused with more than
+    //       one "PREF"s in one property name, while Android accepts them.
     public static final String ATTR_TYPE_PREF = "PREF";
 
     // Phone types valid in vCard and known to ContactsContract, but not so common.
     public static final String ATTR_TYPE_CAR = "CAR";
     public static final String ATTR_TYPE_ISDN = "ISDN";
     public static final String ATTR_TYPE_PAGER = "PAGER";
+    public static final String ATTR_TYPE_TLX = "TLX";  // Telex
 
     // Phone types existing in vCard 2.1 but not known to ContactsContract.
     // TODO: should make parser make these TYPE_CUSTOM.
@@ -118,16 +126,16 @@
     public static final String ATTR_TYPE_VIDEO = "VIDEO";
 
     // Attribute for Phones, which are not formally valid in vCard (at least 2.1).
-    // These types are encoded to "X-" attributes when composing vCard for now.
-    // Parser passes these even if "X-" is added to the attribute.
-    public static final String ATTR_PHONE_EXTRA_TYPE_OTHER = "OTHER";
+    // These types are basically encoded to "X-" attributes when composing vCard.
+    // Parser passes these when "X-" is added to the attribute or not.
     public static final String ATTR_PHONE_EXTRA_TYPE_CALLBACK = "CALLBACK";
-    // TODO: may be "TYPE=COMPANY,PREF", not "COMPANY-MAIN".
-    public static final String ATTR_PHONE_EXTRA_TYPE_COMPANY_MAIN = "COMPANY-MAIN";
     public static final String ATTR_PHONE_EXTRA_TYPE_RADIO = "RADIO";
-    public static final String ATTR_PHONE_EXTRA_TYPE_TELEX = "TELEX";
     public static final String ATTR_PHONE_EXTRA_TYPE_TTY_TDD = "TTY-TDD";
     public static final String ATTR_PHONE_EXTRA_TYPE_ASSISTANT = "ASSISTANT";
+    // vCard composer translates this type to "WORK" + "PREF". Just for parsing.
+    public static final String ATTR_PHONE_EXTRA_TYPE_COMPANY_MAIN = "COMPANY-MAIN";
+    // vCard composer translates this type to "VOICE" Just for parsing.
+    public static final String ATTR_PHONE_EXTRA_TYPE_OTHER = "OTHER";
 
     // Attribute for addresses.
     public static final String ATTR_ADR_TYPE_PARCEL = "PARCEL";
@@ -142,6 +150,14 @@
     // vCard 3.0.
     public static final String ATTR_TYPE_X_IRMC_N = "X-IRMC-N";
 
+    public interface ImportOnly {
+        public static final String PROPERTY_X_NICKNAME = "X-NICKNAME";
+        // Some device emits this "X-" attribute for expressing Google Talk,
+        // which is specifically invalid but should be always properly accepted, and emitted
+        // in some special case (for that device/application).
+        public static final String PROPERTY_X_GOOGLE_TALK_WITH_SPACE = "X-GOOGLE TALK";
+    }
+
     private Constants() {
     }
 }
\ No newline at end of file
diff --git a/core/java/android/pim/vcard/ContactStruct.java b/core/java/android/pim/vcard/ContactStruct.java
index 046fb02..eb9c48a 100644
--- a/core/java/android/pim/vcard/ContactStruct.java
+++ b/core/java/android/pim/vcard/ContactStruct.java
@@ -68,7 +68,8 @@
         sImMap.put(Constants.PROPERTY_X_JABBER, Im.PROTOCOL_JABBER);
         sImMap.put(Constants.PROPERTY_X_SKYPE_USERNAME, Im.PROTOCOL_SKYPE);
         sImMap.put(Constants.PROPERTY_X_GOOGLE_TALK, Im.PROTOCOL_GOOGLE_TALK);
-        sImMap.put(Constants.PROPERTY_X_GOOGLE_TALK_WITH_SPACE, Im.PROTOCOL_GOOGLE_TALK);
+        sImMap.put(Constants.ImportOnly.PROPERTY_X_GOOGLE_TALK_WITH_SPACE,
+                Im.PROTOCOL_GOOGLE_TALK);
     }
     
     static public class PhoneData {
@@ -292,16 +293,18 @@
     }
     
     static public class ImData {
+        public final int protocol;
+        public final String customProtocol;
         public final int type;
         public final String data;
-        public final String label;
         public final boolean isPrimary;
         
-        // TODO: ContactsConstant#PROTOCOL, ContactsConstant#CUSTOM_PROTOCOL should be used?
-        public ImData(int type, String data, String label, boolean isPrimary) {
+        public ImData(int protocol, String customProtocol, int type,
+                String data, boolean isPrimary) {
+            this.protocol = protocol;
+            this.customProtocol = customProtocol;
             this.type = type;
             this.data = data;
-            this.label = label;
             this.isPrimary = isPrimary;
         }
         
@@ -311,14 +314,18 @@
                 return false;
             }
             ImData imData = (ImData)obj;
-            return (type == imData.type && data.equals(imData.data) &&
-                    label.equals(imData.label) && isPrimary == imData.isPrimary);
+            return (type == imData.type && protocol == imData.protocol
+                    && (customProtocol != null ? customProtocol.equals(imData.customProtocol) :
+                        (imData.customProtocol == null))
+                    && (data != null ? data.equals(imData.data) : (imData.data == null))
+                    && isPrimary == imData.isPrimary);
         }
         
         @Override
         public String toString() {
-            return String.format("type: %d, data: %s, label: %s, isPrimary: %s",
-                    type, data, label, isPrimary);
+            return String.format(
+                    "type: %d, protocol: %d, custom_protcol: %s, data: %s, isPrimary: %s",
+                    type, protocol, customProtocol, data, isPrimary);
         }
     }
     
@@ -440,7 +447,7 @@
     private final Account mAccount;
 
     public ContactStruct() {
-        this(VCardConfig.VCARD_TYPE_V21_GENERIC);
+        this(VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
     }
 
     public ContactStruct(int vcardType) {
@@ -619,11 +626,12 @@
         addNewOrganization(DEFAULT_ORGANIZATION_TYPE, null, null, title, false);
     }
 
-    private void addIm(int type, String data, String label, boolean isPrimary) {
+    private void addIm(int protocol, String customProtocol, int type,
+            String propValue, boolean isPrimary) {
         if (mImList == null) {
             mImList = new ArrayList<ImData>();
         }
-        mImList.add(new ImData(type, data, label, isPrimary));
+        mImList.add(new ImData(protocol, customProtocol, type, propValue, isPrimary));
     }
     
     private void addNote(final String note) {
@@ -720,7 +728,7 @@
         } else if (propName.equals(Constants.PROPERTY_NICKNAME)) {
             mPhoneticFullName = propValue;
         } else if (propName.equals(Constants.PROPERTY_NICKNAME) ||
-                propName.equals(Constants.PROPERTY_X_NICKNAME)) {
+                propName.equals(Constants.ImportOnly.PROPERTY_X_NICKNAME)) {
             addNickName(propValue);
         } else if (propName.equals(Constants.PROPERTY_SOUND)) {
             Collection<String> typeCollection = paramMap.get(Constants.ATTR_TYPE);
@@ -891,25 +899,28 @@
                 isPrimary = false;
             }
             addPhone(type, propValue, label, isPrimary);
-        } else if (sImMap.containsKey(propName)){
-            int type = sImMap.get(propName);
+        } else if (sImMap.containsKey(propName)) {
+            final int protocol = sImMap.get(propName);
             boolean isPrimary = false;
+            int type = -1;
             final Collection<String> typeCollection = paramMap.get(Constants.ATTR_TYPE);
             if (typeCollection != null) {
                 for (String typeString : typeCollection) {
                     if (typeString.equals(Constants.ATTR_TYPE_PREF)) {
                         isPrimary = true;
-                    } else if (typeString.equalsIgnoreCase(Constants.ATTR_TYPE_HOME)) {
-                        type = Phone.TYPE_HOME;
-                    } else if (typeString.equalsIgnoreCase(Constants.ATTR_TYPE_WORK)) {
-                        type = Phone.TYPE_WORK;
+                    } else if (type < 0) {
+                        if (typeString.equalsIgnoreCase(Constants.ATTR_TYPE_HOME)) {
+                            type = Im.TYPE_HOME;
+                        } else if (typeString.equalsIgnoreCase(Constants.ATTR_TYPE_WORK)) {
+                            type = Im.TYPE_WORK;
+                        }
                     }
                 }
             }
             if (type < 0) {
                 type = Phone.TYPE_HOME;
             }
-            addIm(type, propValue, null, isPrimary);
+            addIm(protocol, null, type, propValue, isPrimary);
         } else if (propName.equals(Constants.PROPERTY_NOTE)) {
             addNote(propValue);
         } else if (propName.equals(Constants.PROPERTY_URL)) {
@@ -1158,10 +1169,10 @@
                 builder.withValueBackReference(Im.RAW_CONTACT_ID, 0);
                 builder.withValue(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
                 builder.withValue(Im.TYPE, imData.type);
-                if (imData.type == Im.TYPE_CUSTOM) {
-                    builder.withValue(Im.LABEL, imData.label);
+                builder.withValue(Im.PROTOCOL, imData.protocol);
+                if (imData.protocol == Im.PROTOCOL_CUSTOM) {
+                    builder.withValue(Im.CUSTOM_PROTOCOL, imData.customProtocol);
                 }
-                builder.withValue(Im.DATA, imData.data);
                 if (imData.isPrimary) {
                     builder.withValue(Data.IS_PRIMARY, 1);
                 }
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index 9cb9c90..c5afb73 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -100,7 +100,10 @@
 public class VCardComposer {
     private static final String LOG_TAG = "vcard.VCardComposer";
 
-    private static final String DEFAULT_EMAIL_TYPE = Constants.ATTR_TYPE_INTERNET;
+    // TODO: Should be configurable?
+    public static final int DEFAULT_PHONE_TYPE = Phone.TYPE_HOME;
+    public static final int DEFAULT_POSTAL_TYPE = StructuredPostal.TYPE_HOME;
+    public static final int DEFAULT_EMAIL_TYPE = Email.TYPE_OTHER;
 
     public static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO =
         "Failed to get database information";
@@ -154,6 +157,11 @@
     private static final Uri sDataRequestUri;
     private static final Map<Integer, String> sImMap;
 
+    /**
+     * See the comment in {@link VCardConfig#FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES}.
+     */
+    private static final Set<String> sPrimaryPropertyNameSet;
+
     static {
         Uri.Builder builder = RawContacts.CONTENT_URI.buildUpon();
         builder.appendQueryParameter(Data.FOR_EXPORT_ONLY, "1");
@@ -166,6 +174,12 @@
         sImMap.put(Im.PROTOCOL_JABBER, Constants.PROPERTY_X_JABBER);
         sImMap.put(Im.PROTOCOL_SKYPE, Constants.PROPERTY_X_SKYPE_USERNAME);
         // Google talk is a special case.
+
+        // TODO: incomplete. Implement properly
+        sPrimaryPropertyNameSet = new HashSet<String>();
+        sPrimaryPropertyNameSet.add(Constants.PROPERTY_N);
+        sPrimaryPropertyNameSet.add(Constants.PROPERTY_FN);
+        sPrimaryPropertyNameSet.add(Constants.PROPERTY_SOUND);
     }
 
     public static interface OneEntryHandler {
@@ -287,8 +301,9 @@
     private final boolean mUsesDefactProperty;
     private final boolean mUsesUtf8;
     private final boolean mUsesShiftJis;
-    private final boolean mUsesQPToPrimaryProperties;
     private final boolean mAppendTypeParamName;
+    private final boolean mRefrainsQPToPrimaryProperties;
+    private final boolean mNeedsToConvertPhoneticString;
 
     private Cursor mCursor;
     private int mIdColumn;
@@ -353,8 +368,9 @@
         mUsesDefactProperty = VCardConfig.usesDefactProperty(vcardType);
         mUsesUtf8 = VCardConfig.usesUtf8(vcardType);
         mUsesShiftJis = VCardConfig.usesShiftJis(vcardType);
-        mUsesQPToPrimaryProperties = VCardConfig.usesQPToPrimaryProperties(vcardType);
+        mRefrainsQPToPrimaryProperties = VCardConfig.refrainsQPToPrimaryProperties(vcardType);
         mAppendTypeParamName = VCardConfig.appendTypeParamName(vcardType);
+        mNeedsToConvertPhoneticString = VCardConfig.needsToConvertPhoneticString(vcardType);
         mHandlerList = new ArrayList<OneEntryHandler>();
 
         if (mIsDoCoMo) {
@@ -569,7 +585,7 @@
         appendOrganizations(builder, contentValuesListMap);
         appendPhotos(builder, contentValuesListMap);
         appendNotes(builder, contentValuesListMap);
-        // TODO: GroupMembership
+        // TODO: GroupMembership, Relation, Event other than birthday.
 
         if (mIsDoCoMo) {
             appendVCardLine(builder, Constants.PROPERTY_X_CLASS, VCARD_DATA_PUBLIC);
@@ -650,21 +666,38 @@
         // may get confused with multiple "N", "FN", etc. properties, though it is valid in
         // vCard spec.
         ContentValues primaryContentValues = null;
+        ContentValues subprimaryContentValues = null;
         for (ContentValues contentValues : contentValuesList) {
+            if (contentValues == null){
+                continue;
+            }
             Integer isSuperPrimary = contentValues.getAsInteger(StructuredName.IS_SUPER_PRIMARY);
-            if (isSuperPrimary != null && isSuperPrimary != 0) {
+            if (isSuperPrimary != null && isSuperPrimary > 0) {
                 // We choose "super primary" ContentValues.
                 primaryContentValues = contentValues;
                 break;
-            } else if (primaryContentValues == null && contentValues != null) {
-                // We choose the first ContentValues if "super primary" ContentValues does not exist.
-                primaryContentValues = contentValues;
+            } else if (primaryContentValues == null) {
+                // We choose the first "primary" ContentValues
+                // if "super primary" ContentValues does not exist.
+                Integer primary = contentValues.getAsInteger(StructuredName.IS_PRIMARY);
+                if (primary != null && primary > 0) {
+                    primaryContentValues = contentValues;
+                    // Do not break, since there may be ContentValues with "super primary"
+                    // afterword.
+                } else if (subprimaryContentValues == null) {
+                    subprimaryContentValues = contentValues;
+                }
             }
         }
 
         if (primaryContentValues == null) {
-            Log.e(LOG_TAG, "All ContentValues given from database is empty.");
-            primaryContentValues = new ContentValues();
+            if (subprimaryContentValues != null) {
+                // We choose the first ContentValues if any "primary" ContentValues does not exist.
+                primaryContentValues = subprimaryContentValues;
+            } else {
+                Log.e(LOG_TAG, "All ContentValues given from database is empty.");
+                primaryContentValues = new ContentValues();
+            }
         }
 
         final String familyName = primaryContentValues
@@ -688,7 +721,7 @@
             final String encodedSuffix;
 
             final boolean reallyUseQuotedPrintableToName =
-                (mUsesQPToPrimaryProperties &&
+                (!mRefrainsQPToPrimaryProperties &&
                     !(VCardUtils.containsOnlyNonCrLfPrintableAscii(familyName) &&
                             VCardUtils.containsOnlyNonCrLfPrintableAscii(givenName) &&
                             VCardUtils.containsOnlyNonCrLfPrintableAscii(middleName) &&
@@ -733,17 +766,17 @@
             builder.append(encodedSuffix);
             builder.append(VCARD_COL_SEPARATOR);
 
-            final String fullname = VCardUtils.constructNameFromElements(
+            final String formattedName = VCardUtils.constructNameFromElements(
                     VCardConfig.getNameOrderType(mVCardType),
                     encodedFamily, encodedMiddle, encodedGiven, encodedPrefix, encodedSuffix);
             final boolean reallyUseQuotedPrintableToFullname =
-                mUsesQPToPrimaryProperties &&
-                !VCardUtils.containsOnlyNonCrLfPrintableAscii(fullname);
+                !mRefrainsQPToPrimaryProperties &&
+                !VCardUtils.containsOnlyNonCrLfPrintableAscii(formattedName);
 
             final String encodedFullname =
                 reallyUseQuotedPrintableToFullname ?
-                        encodeQuotedPrintable(fullname) :
-                            escapeCharacters(fullname);
+                        encodeQuotedPrintable(formattedName) :
+                            escapeCharacters(formattedName);
 
             // FN property
             builder.append(Constants.PROPERTY_FN);
@@ -760,7 +793,7 @@
             builder.append(VCARD_COL_SEPARATOR);
         } else if (!TextUtils.isEmpty(displayName)) {
             final boolean reallyUseQuotedPrintableToDisplayName =
-                (mUsesQPToPrimaryProperties &&
+                (!mRefrainsQPToPrimaryProperties &&
                         !VCardUtils.containsOnlyNonCrLfPrintableAscii(displayName));
             final String encodedDisplayName =
                     reallyUseQuotedPrintableToDisplayName ?
@@ -783,37 +816,53 @@
             builder.append(VCARD_ITEM_SEPARATOR);
             builder.append(VCARD_ITEM_SEPARATOR);
             builder.append(VCARD_COL_SEPARATOR);
-        } else if (mIsDoCoMo) {
-            appendVCardLine(builder, Constants.PROPERTY_N, "");
+            if (mIsV30) {
+                builder.append(Constants.PROPERTY_FN);
+                // TODO: Not allowed formally...
+                if (shouldAppendCharsetAttribute(encodedDisplayName)) {
+                    builder.append(VCARD_ATTR_SEPARATOR);
+                    builder.append(mVCardAttributeCharset);
+                }
+                builder.append(VCARD_DATA_SEPARATOR);
+                builder.append(encodedDisplayName);
+                builder.append(VCARD_COL_SEPARATOR);
+            }
         } else if (mIsV30) {
+            // vCard 3.0 specification requires these fields.
             appendVCardLine(builder, Constants.PROPERTY_N, "");
             appendVCardLine(builder, Constants.PROPERTY_FN, "");
+        } else if (mIsDoCoMo) {
+            appendVCardLine(builder, Constants.PROPERTY_N, "");
         }
 
-        String phoneticFamilyName = primaryContentValues
-                .getAsString(StructuredName.PHONETIC_FAMILY_NAME);
-        String phoneticMiddleName = primaryContentValues
-                .getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
-        String phoneticGivenName = primaryContentValues
-                .getAsString(StructuredName.PHONETIC_GIVEN_NAME);
-        if (!(TextUtils.isEmpty(phoneticFamilyName)
-                && TextUtils.isEmpty(phoneticMiddleName) &&
-                TextUtils.isEmpty(phoneticGivenName))) { // if not empty
-            if (mIsJapaneseMobilePhone) {
-                phoneticFamilyName = VCardUtils
-                        .toHalfWidthString(phoneticFamilyName);
-                phoneticMiddleName = VCardUtils
-                        .toHalfWidthString(phoneticMiddleName);
-                phoneticGivenName = VCardUtils
-                        .toHalfWidthString(phoneticGivenName);
+        final String phoneticFamilyName;
+        final String phoneticMiddleName;
+        final String phoneticGivenName;
+        {
+            String tmpPhoneticFamilyName =
+                primaryContentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
+            String tmpPhoneticMiddleName =
+                primaryContentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
+            String tmpPhoneticGivenName =
+                primaryContentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
+            if (mNeedsToConvertPhoneticString) {
+                phoneticFamilyName = VCardUtils.toHalfWidthString(tmpPhoneticFamilyName);
+                phoneticMiddleName = VCardUtils.toHalfWidthString(tmpPhoneticMiddleName);
+                phoneticGivenName = VCardUtils.toHalfWidthString(tmpPhoneticGivenName);
+            } else {
+                phoneticFamilyName = tmpPhoneticFamilyName;
+                phoneticMiddleName = tmpPhoneticMiddleName;
+                phoneticGivenName = tmpPhoneticGivenName;
             }
+        }
+        if (!(TextUtils.isEmpty(phoneticFamilyName)
+                && TextUtils.isEmpty(phoneticMiddleName)
+                && TextUtils.isEmpty(phoneticGivenName))) {
 
             if (mIsV30) {
                 final String sortString = VCardUtils
                         .constructNameFromElements(mVCardType,
-                                phoneticFamilyName,
-                                phoneticMiddleName,
-                                phoneticGivenName);
+                                phoneticFamilyName, phoneticMiddleName, phoneticGivenName);
                 builder.append(Constants.PROPERTY_SORT_STRING);
 
                 // Do not need to care about QP, since vCard 3.0 does not allow it.
@@ -825,11 +874,12 @@
                 builder.append(VCARD_DATA_SEPARATOR);
                 builder.append(encodedSortString);
                 builder.append(VCARD_COL_SEPARATOR);
-            } else {
+            } else if (mIsJapaneseMobilePhone) {
                 // Note: There is no appropriate property for expressing
                 //       phonetic name in vCard 2.1, while there is in
                 //       vCard 3.0 (SORT-STRING).
-                //       We chose to use DoCoMo's way since it is supported by
+                //       We chose to use DoCoMo's way when the device is Japanese one
+                //       since it is supported by
                 //       a lot of Japanese mobile phones. This is "X-" property, so
                 //       any parser hopefully would not get confused with this.
                 builder.append(Constants.PROPERTY_SOUND);
@@ -837,13 +887,13 @@
                 builder.append(Constants.ATTR_TYPE_X_IRMC_N);
 
                 boolean reallyUseQuotedPrintable =
-                    (mUsesQPToPrimaryProperties &&
-                            !(VCardUtils.containsOnlyNonCrLfPrintableAscii(
-                                    phoneticFamilyName) &&
-                              VCardUtils.containsOnlyNonCrLfPrintableAscii(
-                                    phoneticMiddleName) &&
-                              VCardUtils.containsOnlyNonCrLfPrintableAscii(
-                                    phoneticGivenName)));
+                    (!mRefrainsQPToPrimaryProperties
+                            && !(VCardUtils.containsOnlyNonCrLfPrintableAscii(
+                                    phoneticFamilyName)
+                                    && VCardUtils.containsOnlyNonCrLfPrintableAscii(
+                                            phoneticMiddleName)
+                                    && VCardUtils.containsOnlyNonCrLfPrintableAscii(
+                                            phoneticGivenName)));
 
                 final String encodedPhoneticFamilyName;
                 final String encodedPhoneticMiddleName;
@@ -889,8 +939,7 @@
         if (mUsesDefactProperty) {
             if (!TextUtils.isEmpty(phoneticGivenName)) {
                 final boolean reallyUseQuotedPrintable =
-                    (mUsesQPToPrimaryProperties &&
-                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName));
+                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName);
                 final String encodedPhoneticGivenName;
                 if (reallyUseQuotedPrintable) {
                     encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName);
@@ -912,8 +961,7 @@
             }
             if (!TextUtils.isEmpty(phoneticMiddleName)) {
                 final boolean reallyUseQuotedPrintable =
-                    (mUsesQPToPrimaryProperties &&
-                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName));
+                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName);
                 final String encodedPhoneticMiddleName;
                 if (reallyUseQuotedPrintable) {
                     encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName);
@@ -935,8 +983,7 @@
             }
             if (!TextUtils.isEmpty(phoneticFamilyName)) {
                 final boolean reallyUseQuotedPrintable =
-                    (mUsesQPToPrimaryProperties &&
-                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName));
+                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName);
                 final String encodedPhoneticFamilyName;
                 if (reallyUseQuotedPrintable) {
                     encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName);
@@ -963,46 +1010,48 @@
             final Map<String, List<ContentValues>> contentValuesListMap) {
         final List<ContentValues> contentValuesList = contentValuesListMap
                 .get(Nickname.CONTENT_ITEM_TYPE);
-        if (contentValuesList != null) {
-            final String propertyNickname;
-            if (mIsV30) {
-                propertyNickname = Constants.PROPERTY_NICKNAME;
-            /*} else if (mUsesAndroidProperty) {
-                propertyNickname = VCARD_PROPERTY_X_NICKNAME;*/
+        if (contentValuesList == null) {
+            return;
+        }
+
+        final String propertyNickname;
+        if (mIsV30) {
+            propertyNickname = Constants.PROPERTY_NICKNAME;
+        /*} else if (mUsesAndroidProperty) {
+            propertyNickname = VCARD_PROPERTY_X_NICKNAME;*/
+        } else {
+            // There's no way to add this field.
+            return;
+        }
+
+        for (ContentValues contentValues : contentValuesList) {
+            final String nickname = contentValues.getAsString(Nickname.NAME);
+            if (TextUtils.isEmpty(nickname)) {
+                continue;
+            }
+
+            final String encodedNickname;
+            final boolean reallyUseQuotedPrintable =
+                (mUsesQuotedPrintable &&
+                        !VCardUtils.containsOnlyNonCrLfPrintableAscii(nickname));
+            if (reallyUseQuotedPrintable) {
+                encodedNickname = encodeQuotedPrintable(nickname);
             } else {
-                // There's no way to add this field.
-                return;
+                encodedNickname = escapeCharacters(nickname);
             }
 
-            for (ContentValues contentValues : contentValuesList) {
-                final String nickname = contentValues.getAsString(Nickname.NAME);
-                if (TextUtils.isEmpty(nickname)) {
-                    continue;
-                }
-
-                final String encodedNickname;
-                final boolean reallyUseQuotedPrintable =
-                    (mUsesQuotedPrintable &&
-                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(nickname));
-                if (reallyUseQuotedPrintable) {
-                    encodedNickname = encodeQuotedPrintable(nickname);
-                } else {
-                    encodedNickname = escapeCharacters(nickname);
-                }
-
-                builder.append(propertyNickname);
-                if (shouldAppendCharsetAttribute(propertyNickname)) {
-                    builder.append(VCARD_ATTR_SEPARATOR);
-                    builder.append(mVCardAttributeCharset);
-                }
-                if (reallyUseQuotedPrintable) {
-                    builder.append(VCARD_ATTR_SEPARATOR);
-                    builder.append(VCARD_ATTR_ENCODING_QP);
-                }
-                builder.append(VCARD_DATA_SEPARATOR);
-                builder.append(encodedNickname);
-                builder.append(VCARD_COL_SEPARATOR);
+            builder.append(propertyNickname);
+            if (shouldAppendCharsetAttribute(propertyNickname)) {
+                builder.append(VCARD_ATTR_SEPARATOR);
+                builder.append(mVCardAttributeCharset);
             }
+            if (reallyUseQuotedPrintable) {
+                builder.append(VCARD_ATTR_SEPARATOR);
+                builder.append(VCARD_ATTR_ENCODING_QP);
+            }
+            builder.append(VCARD_DATA_SEPARATOR);
+            builder.append(encodedNickname);
+            builder.append(VCARD_COL_SEPARATOR);
         }
     }
 
@@ -1016,6 +1065,9 @@
             for (ContentValues contentValues : contentValuesList) {
                 final Integer typeAsObject = contentValues.getAsInteger(Phone.TYPE);
                 final String label = contentValues.getAsString(Phone.LABEL);
+                final Integer isPrimaryAsInteger = contentValues.getAsInteger(Phone.IS_PRIMARY);
+                final boolean isPrimary = (isPrimaryAsInteger != null ?
+                        (isPrimaryAsInteger > 0) : false);
                 String phoneNumber = contentValues.getAsString(Phone.NUMBER);
                 if (phoneNumber != null) {
                     phoneNumber = phoneNumber.trim();
@@ -1024,18 +1076,18 @@
                     continue;
                 }
                 phoneLineExists = true;
-                int type = (typeAsObject != null ? typeAsObject : Phone.TYPE_HOME);
+                int type = (typeAsObject != null ? typeAsObject : DEFAULT_PHONE_TYPE);
                 // TODO: Premature, since this allows two phone numbers which are
                 //        same from the view of phone number format (e.g. "100" v.s. "1-0-0")
                 if (!phoneSet.contains(phoneNumber)) {
                     phoneSet.add(phoneNumber);
-                    appendVCardTelephoneLine(builder, type, label, phoneNumber);
+                    appendVCardTelephoneLine(builder, type, label, phoneNumber, isPrimary);
                 }
             }
         }
 
         if (!phoneLineExists && mIsDoCoMo) {
-            appendVCardTelephoneLine(builder, Phone.TYPE_HOME, "", "");
+            appendVCardTelephoneLine(builder, Phone.TYPE_HOME, "", "", false);
         }
     }
 
@@ -1043,14 +1095,11 @@
             final Map<String, List<ContentValues>> contentValuesListMap) {
         final List<ContentValues> contentValuesList = contentValuesListMap
                 .get(Email.CONTENT_ITEM_TYPE);
+
         boolean emailAddressExists = false;
         if (contentValuesList != null) {
-            Set<String> addressSet = new HashSet<String>();
+            final Set<String> addressSet = new HashSet<String>();
             for (ContentValues contentValues : contentValuesList) {
-                Integer typeAsObject = contentValues.getAsInteger(Email.TYPE);
-                final int type = (typeAsObject != null ?
-                        typeAsObject : Email.TYPE_OTHER);
-                final String label = contentValues.getAsString(Email.LABEL);
                 String emailAddress = contentValues.getAsString(Email.DATA);
                 if (emailAddress != null) {
                     emailAddress = emailAddress.trim();
@@ -1058,16 +1107,23 @@
                 if (TextUtils.isEmpty(emailAddress)) {
                     continue;
                 }
+                Integer typeAsObject = contentValues.getAsInteger(Email.TYPE);
+                final int type = (typeAsObject != null ?
+                        typeAsObject : DEFAULT_EMAIL_TYPE);
+                final String label = contentValues.getAsString(Email.LABEL);
+                Integer isPrimaryAsInteger = contentValues.getAsInteger(Email.IS_PRIMARY);
+                final boolean isPrimary = (isPrimaryAsInteger != null ?
+                        (isPrimaryAsInteger > 0) : false);
                 emailAddressExists = true;
                 if (!addressSet.contains(emailAddress)) {
                     addressSet.add(emailAddress);
-                    appendVCardEmailLine(builder, type, label, emailAddress);
+                    appendVCardEmailLine(builder, type, label, emailAddress, isPrimary);
                 }
             }
         }
 
         if (!emailAddressExists && mIsDoCoMo) {
-            appendVCardEmailLine(builder, Email.TYPE_HOME, "", "");
+            appendVCardEmailLine(builder, Email.TYPE_HOME, "", "", false);
         }
     }
 
@@ -1124,7 +1180,10 @@
             final Integer type = contentValues.getAsInteger(StructuredPostal.TYPE);
             final String label = contentValues.getAsString(StructuredPostal.LABEL);
             if (type == preferedType) {
-                appendVCardPostalLine(builder, type, label, contentValues);
+                // Note: Not sure why we need to emit "empty" line even when actual
+                //       data does not exist. There may be some reason or may not.
+                //       We keep safer side since the previous implementation did so.
+                appendVCardPostalLine(builder, type, label, contentValues, true, true);
                 return true;
             }
         }
@@ -1134,11 +1193,18 @@
     private void appendPostalsForGeneric(final StringBuilder builder,
             final List<ContentValues> contentValuesList) {
         for (ContentValues contentValues : contentValuesList) {
-            final Integer type = contentValues.getAsInteger(StructuredPostal.TYPE);
-            final String label = contentValues.getAsString(StructuredPostal.LABEL);
-            if (type != null) {
-                appendVCardPostalLine(builder, type, label, contentValues);
+            if (contentValues == null) {
+                continue;
             }
+            final Integer typeAsObject = contentValues.getAsInteger(StructuredPostal.TYPE);
+            final int type = (typeAsObject != null ?
+                    typeAsObject : DEFAULT_POSTAL_TYPE);
+            final String label = contentValues.getAsString(StructuredPostal.LABEL);
+            final Integer isPrimaryAsInteger =
+                contentValues.getAsInteger(StructuredPostal.IS_PRIMARY);
+            final boolean isPrimary = (isPrimaryAsInteger != null ?
+                    (isPrimaryAsInteger > 0) : false);
+            appendVCardPostalLine(builder, type, label, contentValues, isPrimary, false);
         }
     }
 
@@ -1146,24 +1212,63 @@
             final Map<String, List<ContentValues>> contentValuesListMap) {
         final List<ContentValues> contentValuesList = contentValuesListMap
                 .get(Im.CONTENT_ITEM_TYPE);
-        if (contentValuesList != null) {
-            for (ContentValues contentValues : contentValuesList) {
-                Integer protocol = contentValues.getAsInteger(Im.PROTOCOL);
-                String data = contentValues.getAsString(Im.DATA);
-                if (data != null) {
-                    data = data.trim();
-                }
-                if (TextUtils.isEmpty(data)) {
-                    continue;
-                }
-
-                if (protocol != null && protocol == Im.PROTOCOL_GOOGLE_TALK) {
-                    if (VCardConfig.usesAndroidSpecificProperty(mVCardType)) {
-                        appendVCardLine(builder, Constants.PROPERTY_X_GOOGLE_TALK, data);
+        if (contentValuesList == null) {
+            return;
+        }
+        for (ContentValues contentValues : contentValuesList) {
+            final Integer protocolAsObject = contentValues.getAsInteger(Im.PROTOCOL);
+            if (protocolAsObject == null) {
+                continue;
+            }
+            final String propertyName = VCardUtils.getPropertyNameForIm(protocolAsObject);
+            if (propertyName == null) {
+                continue;
+            }
+            String data = contentValues.getAsString(Im.DATA);
+            if (data != null) {
+                data = data.trim();
+            }
+            if (TextUtils.isEmpty(data)) {
+                continue;
+            }
+            final String typeAsString;
+            {
+                final Integer typeAsInteger = contentValues.getAsInteger(Im.TYPE);
+                switch (typeAsInteger != null ? typeAsInteger : Im.TYPE_OTHER) {
+                    case Im.TYPE_HOME: {
+                        typeAsString = Constants.ATTR_TYPE_HOME;
+                        break;
                     }
-                    // TODO: add "X-GOOGLE TALK" case...
+                    case Im.TYPE_WORK: {
+                        typeAsString = Constants.ATTR_TYPE_WORK;
+                        break;
+                    }
+                    case Im.TYPE_CUSTOM: {
+                        final String label = contentValues.getAsString(Im.LABEL);
+                        typeAsString = (label != null ? "X-" + label : null);
+                        break;
+                    }
+                    case Im.TYPE_OTHER:  // Ignore
+                    default: {
+                        typeAsString = null;
+                        break;
+                    }
                 }
             }
+
+            List<String> attributeList = new ArrayList<String>();
+            if (!TextUtils.isEmpty(typeAsString)) {
+                attributeList.add(typeAsString);
+            }
+            final Integer isPrimaryAsInteger = contentValues.getAsInteger(Im.IS_PRIMARY);
+            final boolean isPrimary = (isPrimaryAsInteger != null ?
+                    (isPrimaryAsInteger > 0) : false);
+            if (isPrimary) {
+                attributeList.add(Constants.ATTR_TYPE_PREF);
+            }
+
+            appendVCardLineWithCharsetAndQPDetection(
+                    builder, propertyName, attributeList, data);
         }
     }
 
@@ -1171,39 +1276,83 @@
             final Map<String, List<ContentValues>> contentValuesListMap) {
         final List<ContentValues> contentValuesList = contentValuesListMap
                 .get(Website.CONTENT_ITEM_TYPE);
-        if (contentValuesList != null) {
-            for (ContentValues contentValues : contentValuesList) {
-                String website = contentValues.getAsString(Website.URL);
-                if (website != null) {
-                    website = website.trim();
-                }
-                if (!TextUtils.isEmpty(website)) {
-                    appendVCardLine(builder, Constants.PROPERTY_URL, website);
-                }
+        if (contentValuesList == null) {
+            return;
+        }
+        for (ContentValues contentValues : contentValuesList) {
+            String website = contentValues.getAsString(Website.URL);
+            if (website != null) {
+                website = website.trim();
+            }
+            // Note: vCard 3.0 does not allow any attribute addition toward "URL"
+            //       property, while there's no document in vCard 2.1.
+            //
+            // TODO: Should we allow adding it when appropriate?
+            //       (Actually, we drop some data. Using "group.X-URL-TYPE" or something
+            //        may help)
+            if (!TextUtils.isEmpty(website)) {
+                appendVCardLine(builder, Constants.PROPERTY_URL, website);
             }
         }
     }
 
+    /**
+     * Theoretically, there must be only one birthday for each vCard entry.
+     * Also, we are afraid of some importer's parse error during its import.
+     * We emit only one birthday entry even when there are more than one.
+     */
     private void appendBirthday(final StringBuilder builder,
             final Map<String, List<ContentValues>> contentValuesListMap) {
-        final List<ContentValues> contentValuesList = contentValuesListMap
-                .get(Event.CONTENT_ITEM_TYPE);
-        if (contentValuesList != null && contentValuesList.size() > 0) {
-            Integer eventType = contentValuesList.get(0).getAsInteger(Event.TYPE);
+        final List<ContentValues> contentValuesList =
+                contentValuesListMap.get(Event.CONTENT_ITEM_TYPE);
+        if (contentValuesList == null) {
+            return;
+        }
+        String primaryBirthday = null;
+        String secondaryBirthday = null;
+        for (ContentValues contentValues : contentValuesList) {
+            if (contentValues == null) {
+                continue;
+            }
+            final Integer eventType = contentValues.getAsInteger(Event.TYPE);
             if (eventType == null || !eventType.equals(Event.TYPE_BIRTHDAY)) {
-                return;
+                continue;
             }
-            // Theoretically, there must be only one birthday for each vCard data and
-            // we are afraid of some parse error occuring in some devices, so
-            // we emit only one birthday entry for now.
-            String birthday = contentValuesList.get(0).getAsString(Event.START_DATE);
-            if (birthday != null) {
-                birthday = birthday.trim();
+            final String birthdayCandidate = contentValues.getAsString(Event.START_DATE);
+            if (birthdayCandidate == null) {
+                continue;
             }
-            if (!TextUtils.isEmpty(birthday)) {
-                appendVCardLine(builder, Constants.PROPERTY_BDAY, birthday);
+            final Integer isSuperPrimaryAsInteger =
+                contentValues.getAsInteger(Event.IS_SUPER_PRIMARY);
+            final boolean isSuperPrimary = (isSuperPrimaryAsInteger != null ?
+                    (isSuperPrimaryAsInteger > 0) : false);
+            if (isSuperPrimary) {
+                // "super primary" birthday should the prefered one.
+                primaryBirthday = birthdayCandidate;
+                break;
+            }
+            final Integer isPrimaryAsInteger =
+                contentValues.getAsInteger(Event.IS_PRIMARY);
+            final boolean isPrimary = (isPrimaryAsInteger != null ?
+                    (isPrimaryAsInteger > 0) : false);
+            if (isPrimary) {
+                // We don't break here since "super primary" birthday may exist later.
+                primaryBirthday = birthdayCandidate;
+            } else if (secondaryBirthday == null) {
+                // First entry is set to the "secondary" candidate.
+                secondaryBirthday = birthdayCandidate;
             }
         }
+
+        final String birthday;
+        if (primaryBirthday != null) {
+            birthday = primaryBirthday.trim();
+        } else if (secondaryBirthday != null){
+            birthday = secondaryBirthday.trim();
+        } else {
+            return;
+        }
+        appendVCardLineWithCharsetAndQPDetection(builder, Constants.PROPERTY_BDAY, birthday);
     }
 
     private void appendOrganizations(final StringBuilder builder,
@@ -1212,23 +1361,35 @@
                 .get(Organization.CONTENT_ITEM_TYPE);
         if (contentValuesList != null) {
             for (ContentValues contentValues : contentValuesList) {
-                String company = contentValues
-                        .getAsString(Organization.COMPANY);
+                String company = contentValues.getAsString(Organization.COMPANY);
                 if (company != null) {
                     company = company.trim();
                 }
-                String title = contentValues
-                        .getAsString(Organization.TITLE);
+                String department = contentValues.getAsString(Organization.DEPARTMENT);
+                if (department != null) {
+                    department = department.trim();
+                }
+                String title = contentValues.getAsString(Organization.TITLE);
                 if (title != null) {
                     title = title.trim();
                 }
 
+                StringBuilder orgBuilder = new StringBuilder();
                 if (!TextUtils.isEmpty(company)) {
-                    appendVCardLine(builder, Constants.PROPERTY_ORG, company,
-                            !VCardUtils.containsOnlyPrintableAscii(company),
-                            (mUsesQuotedPrintable &&
-                                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(company)));
+                    orgBuilder.append(company);
                 }
+                if (!TextUtils.isEmpty(department)) {
+                    if (orgBuilder.length() > 0) {
+                        orgBuilder.append(';');
+                    }
+                    orgBuilder.append(department);
+                }
+                final String orgline = orgBuilder.toString();
+                appendVCardLine(builder, Constants.PROPERTY_ORG, orgline,
+                        !VCardUtils.containsOnlyPrintableAscii(orgline),
+                        (mUsesQuotedPrintable &&
+                                !VCardUtils.containsOnlyNonCrLfPrintableAscii(orgline)));
+
                 if (!TextUtils.isEmpty(title)) {
                     appendVCardLine(builder, Constants.PROPERTY_TITLE, title,
                             !VCardUtils.containsOnlyPrintableAscii(title),
@@ -1257,11 +1418,9 @@
                     photoType = "GIF";
                 } else if (data.length >= 4 && data[0] == (byte) 0x89
                         && data[1] == 'P' && data[2] == 'N' && data[3] == 'G') {
-                    // Note: vCard 2.1 officially does not support PNG, but we
-                    // may have it
-                    // and using X- word like "X-PNG" may not let importers know
-                    // it is
-                    // PNG. So we use the String "PNG" as is...
+                    // Note: vCard 2.1 officially does not support PNG, but we may
+                    // have it and using X- word like "X-PNG" may not let importers
+                    // know it is PNG. So we use the String "PNG" as is...
                     photoType = "PNG";
                 } else if (data.length >= 2 && data[0] == (byte) 0xff
                         && data[1] == (byte) 0xd8) {
@@ -1435,59 +1594,126 @@
         builder.append(VCARD_COL_SEPARATOR);
     }
 
-    private void appendVCardPostalLine(final StringBuilder builder,
-            final Integer typeAsObject, final String label,
-            final ContentValues contentValues) {
-        builder.append(Constants.PROPERTY_ADR);
-        builder.append(VCARD_ATTR_SEPARATOR);
+    private class PostalStruct {
+        final boolean reallyUseQuotedPrintable;
+        final boolean appendCharset;
+        final String addressData;
+        public PostalStruct(final boolean reallyUseQuotedPrintable,
+                final boolean appendCharset, final String addressData) {
+            this.reallyUseQuotedPrintable = reallyUseQuotedPrintable;
+            this.appendCharset = appendCharset;
+            this.addressData = addressData;
+        }
+    }
 
-        // Note: Not sure why we need to emit "empty" line even when actual data does not exist.
-        // There may be some reason or may not be any. We keep safer side.
-        // TODO: investigate this.
-        boolean dataExists = false;
+    /**
+     * @return null when there's no information available to construct the data.
+     */
+    private PostalStruct tryConstructPostalStruct(ContentValues contentValues) {
+        boolean reallyUseQuotedPrintable = false;
+        boolean appendCharset = false;
+
+        boolean dataArrayExists = false;
         String[] dataArray = VCardUtils.getVCardPostalElements(contentValues);
-        boolean actuallyUseQuotedPrintable = false;
-        boolean shouldAppendCharset = false;
         for (String data : dataArray) {
             if (!TextUtils.isEmpty(data)) {
-                dataExists = true;
-                if (!shouldAppendCharset && !VCardUtils.containsOnlyPrintableAscii(data)) {
-                    shouldAppendCharset = true;
+                dataArrayExists = true;
+                if (!appendCharset && !VCardUtils.containsOnlyPrintableAscii(data)) {
+                    appendCharset = true;
                 }
                 if (mUsesQuotedPrintable && !VCardUtils.containsOnlyNonCrLfPrintableAscii(data)) {
-                    actuallyUseQuotedPrintable = true;
+                    reallyUseQuotedPrintable = true;
                     break;
                 }
             }
         }
 
-        int length = dataArray.length;
-        for (int i = 0; i < length; i++) {
-            String data = dataArray[i];
-            if (!TextUtils.isEmpty(data)) {
-                if (actuallyUseQuotedPrintable) {
-                    dataArray[i] = encodeQuotedPrintable(data);
+        if (dataArrayExists) {
+            StringBuffer addressBuffer = new StringBuffer();
+            boolean first = true;
+            for (String data : dataArray) {
+                if (first) {
+                    first = false;
                 } else {
-                    dataArray[i] = escapeCharacters(data);
+                    addressBuffer.append(VCARD_ITEM_SEPARATOR);
                 }
+                if (!TextUtils.isEmpty(data)) {
+                    if (reallyUseQuotedPrintable) {
+                        addressBuffer.append(encodeQuotedPrintable(data));
+                    } else {
+                        addressBuffer.append(escapeCharacters(data));
+                    }
+                }
+            }
+            return new PostalStruct(reallyUseQuotedPrintable, appendCharset,
+                    addressBuffer.toString());
+        }
+
+        String formattedAddress =
+            contentValues.getAsString(StructuredPostal.FORMATTED_ADDRESS);
+        if (!TextUtils.isEmpty(formattedAddress)) {
+            reallyUseQuotedPrintable =
+                !VCardUtils.containsOnlyPrintableAscii(formattedAddress);
+            appendCharset =
+                !VCardUtils.containsOnlyNonCrLfPrintableAscii(formattedAddress);
+            if (reallyUseQuotedPrintable) {
+                formattedAddress = encodeQuotedPrintable(formattedAddress);
+            } else {
+                formattedAddress = escapeCharacters(formattedAddress);
+            }
+            // We use the second value ("Extended Address").
+            //
+            // adr-value    = 0*6(text-value ";") text-value
+            //              ; PO Box, Extended Address, Street, Locality, Region, Postal
+            //              ; Code, Country Name
+            StringBuffer addressBuffer = new StringBuffer();
+            addressBuffer.append(VCARD_ITEM_SEPARATOR);
+            addressBuffer.append(formattedAddress);
+            addressBuffer.append(VCARD_ITEM_SEPARATOR);
+            addressBuffer.append(VCARD_ITEM_SEPARATOR);
+            addressBuffer.append(VCARD_ITEM_SEPARATOR);
+            addressBuffer.append(VCARD_ITEM_SEPARATOR);
+            addressBuffer.append(VCARD_ITEM_SEPARATOR);
+            return new PostalStruct(
+                    reallyUseQuotedPrintable, appendCharset, addressBuffer.toString());
+        }
+        return null;  // There's no data available.
+    }
+
+    private void appendVCardPostalLine(final StringBuilder builder,
+            final int type, final String label, final ContentValues contentValues,
+            final boolean isPrimary, final boolean emitLineEveryTime) {
+        final boolean reallyUseQuotedPrintable;
+        final boolean appendCharset;
+        final String addressData;
+        {
+            PostalStruct postalStruct = tryConstructPostalStruct(contentValues);
+            if (postalStruct == null) {
+                if (emitLineEveryTime) {
+                    reallyUseQuotedPrintable = false;
+                    appendCharset = false;
+                    addressData = "";
+                } else {
+                    return;
+                }
+            } else {
+                reallyUseQuotedPrintable = postalStruct.reallyUseQuotedPrintable;
+                appendCharset = postalStruct.appendCharset;
+                addressData = postalStruct.addressData;
             }
         }
 
-        final int typeAsPrimitive;
-        if (typeAsObject == null) {
-            typeAsPrimitive = StructuredPostal.TYPE_OTHER;
-        } else {
-            typeAsPrimitive = typeAsObject;
+        List<String> attributeList = new ArrayList<String>();
+        if (isPrimary) {
+            attributeList.add(Constants.ATTR_TYPE_PREF);
         }
-
-        String typeAsString = null;
-        switch (typeAsPrimitive) {
+        switch (type) {
             case StructuredPostal.TYPE_HOME: {
-                typeAsString = Constants.ATTR_TYPE_HOME;
+                attributeList.add(Constants.ATTR_TYPE_HOME);
                 break;
             }
             case StructuredPostal.TYPE_WORK: {
-                typeAsString = Constants.ATTR_TYPE_WORK;
+                attributeList.add(Constants.ATTR_TYPE_WORK);
                 break;
             }
             case StructuredPostal.TYPE_CUSTOM: {
@@ -1497,9 +1723,7 @@
                     // ("IANA-token" in the vCard 3.0 is unclear...)
                     // Just  for safety, we add "X-" at the beggining of each label.
                     // Also checks the label obeys with vCard 3.0 spec.
-                    builder.append("X-");
-                    builder.append(label);
-                    builder.append(VCARD_DATA_SEPARATOR);
+                    attributeList.add("X-" + label);
                 }
                 break;
             }
@@ -1507,82 +1731,56 @@
                 break;
             }
             default: {
-                Log.e(LOG_TAG, "Unknown StructuredPostal type: " + typeAsPrimitive);
+                Log.e(LOG_TAG, "Unknown StructuredPostal type: " + type);
                 break;
             }
         }
 
-        // Attribute(s).
+        // Actual data construction starts from here.
+        // TODO: add a new version of appendVCardLine() for this purpose.
 
+        builder.append(Constants.PROPERTY_ADR);
+        builder.append(VCARD_ATTR_SEPARATOR);
+
+        // Attributes
         {
             boolean shouldAppendAttrSeparator = false;
-            if (typeAsString != null) {
-                appendTypeAttribute(builder, typeAsString);
+            if (!attributeList.isEmpty()) {
+                appendTypeAttributes(builder, attributeList);
                 shouldAppendAttrSeparator = true;
             }
 
-            if (dataExists) {
-                if (shouldAppendCharset) {
-                    // Strictly, vCard 3.0 does not allow exporters to emit charset information,
-                    // but we will add it since the information should be useful for importers,
-                    //
-                    // Assume no parser does not emit error with this attribute in vCard 3.0.
-                    if (shouldAppendAttrSeparator) {
-                        builder.append(VCARD_ATTR_SEPARATOR);
-                    }
-                    builder.append(mVCardAttributeCharset);
-                    shouldAppendAttrSeparator = true;
+            if (appendCharset) {
+                // Strictly, vCard 3.0 does not allow exporters to emit charset information,
+                // but we will add it since the information should be useful for importers,
+                //
+                // Assume no parser does not emit error with this attribute in vCard 3.0.
+                if (shouldAppendAttrSeparator) {
+                    builder.append(VCARD_ATTR_SEPARATOR);
                 }
+                builder.append(mVCardAttributeCharset);
+                shouldAppendAttrSeparator = true;
+            }
 
-                if (actuallyUseQuotedPrintable) {
-                    if (shouldAppendAttrSeparator) {
-                        builder.append(VCARD_ATTR_SEPARATOR);
-                    }
-                    builder.append(VCARD_ATTR_ENCODING_QP);
-                    shouldAppendAttrSeparator = true;
+            if (reallyUseQuotedPrintable) {
+                if (shouldAppendAttrSeparator) {
+                    builder.append(VCARD_ATTR_SEPARATOR);
                 }
+                builder.append(VCARD_ATTR_ENCODING_QP);
+                shouldAppendAttrSeparator = true;
             }
         }
 
-        // Property values.
-
         builder.append(VCARD_DATA_SEPARATOR);
-        if (dataExists) {
-            // The elements in dataArray are already encoded to quoted printable
-            // if needed.
-            // See above.
-            //
-            // TODO: in vCard 3.0, one line may become too huge. Fix this.
-            builder.append(dataArray[0]);
-            builder.append(VCARD_ITEM_SEPARATOR);
-            builder.append(dataArray[1]);
-            builder.append(VCARD_ITEM_SEPARATOR);
-            builder.append(dataArray[2]);
-            builder.append(VCARD_ITEM_SEPARATOR);
-            builder.append(dataArray[3]);
-            builder.append(VCARD_ITEM_SEPARATOR);
-            builder.append(dataArray[4]);
-            builder.append(VCARD_ITEM_SEPARATOR);
-            builder.append(dataArray[5]);
-            builder.append(VCARD_ITEM_SEPARATOR);
-            builder.append(dataArray[6]);
-        }
+        builder.append(addressData);
         builder.append(VCARD_COL_SEPARATOR);
     }
 
     private void appendVCardEmailLine(final StringBuilder builder,
-            final Integer typeAsObject, final String label, final String data) {
-        builder.append(Constants.PROPERTY_EMAIL);
-
-        final int typeAsPrimitive;
-        if (typeAsObject == null) {
-            typeAsPrimitive = Email.TYPE_OTHER;
-        } else {
-            typeAsPrimitive = typeAsObject;
-        }
-
+            final int type, final String label,
+            final String rawData, final boolean isPrimary) {
         final String typeAsString;
-        switch (typeAsPrimitive) {
+        switch (type) {
             case Email.TYPE_CUSTOM: {
                 // For backward compatibility.
                 // Detail: Until Donut, there isn't TYPE_MOBILE for email while there is now.
@@ -1594,7 +1792,7 @@
                         && VCardUtils.containsOnlyAlphaDigitHyphen(label)) {
                     typeAsString = "X-" + label;
                 } else {
-                    typeAsString = DEFAULT_EMAIL_TYPE;
+                    typeAsString = null;
                 }
                 break;
             }
@@ -1607,7 +1805,7 @@
                 break;
             }
             case Email.TYPE_OTHER: {
-                typeAsString = DEFAULT_EMAIL_TYPE;
+                typeAsString = null;
                 break;
             }
             case Email.TYPE_MOBILE: {
@@ -1615,22 +1813,27 @@
                 break;
             }
             default: {
-                Log.e(LOG_TAG, "Unknown Email type: " + typeAsPrimitive);
-                typeAsString = DEFAULT_EMAIL_TYPE;
+                Log.e(LOG_TAG, "Unknown Email type: " + type);
+                typeAsString = null;
                 break;
             }
         }
 
-        builder.append(VCARD_ATTR_SEPARATOR);
-        appendTypeAttribute(builder, typeAsString);
-        builder.append(VCARD_DATA_SEPARATOR);
-        builder.append(data);
-        builder.append(VCARD_COL_SEPARATOR);
+        final List<String> attributeList = new ArrayList<String>();
+        if (isPrimary) {
+            attributeList.add(Constants.ATTR_TYPE_PREF);
+        }
+        if (!TextUtils.isEmpty(typeAsString)) {
+            attributeList.add(typeAsString);
+        }
+
+        appendVCardLineWithCharsetAndQPDetection(builder, Constants.PROPERTY_EMAIL,
+                attributeList, rawData);
     }
 
     private void appendVCardTelephoneLine(final StringBuilder builder,
             final Integer typeAsObject, final String label,
-            String encodedData) {
+            final String encodedData, boolean isPrimary) {
         builder.append(Constants.PROPERTY_TEL);
         builder.append(VCARD_ATTR_SEPARATOR);
 
@@ -1641,53 +1844,102 @@
             typeAsPrimitive = typeAsObject;
         }
 
+        ArrayList<String> attributeList = new ArrayList<String>();
         switch (typeAsPrimitive) {
         case Phone.TYPE_HOME:
-            appendTypeAttributes(builder, Arrays.asList(
-                    Constants.ATTR_TYPE_HOME, Constants.ATTR_TYPE_VOICE));
+            attributeList.addAll(
+                    Arrays.asList(Constants.ATTR_TYPE_HOME, Constants.ATTR_TYPE_VOICE));
             break;
         case Phone.TYPE_WORK:
-            appendTypeAttributes(builder, Arrays.asList(
-                    Constants.ATTR_TYPE_WORK, Constants.ATTR_TYPE_VOICE));
+            attributeList.addAll(
+                    Arrays.asList(Constants.ATTR_TYPE_WORK, Constants.ATTR_TYPE_VOICE));
             break;
         case Phone.TYPE_FAX_HOME:
-            appendTypeAttributes(builder, Arrays.asList(
-                    Constants.ATTR_TYPE_HOME, Constants.ATTR_TYPE_FAX));
+            attributeList.addAll(
+                    Arrays.asList(Constants.ATTR_TYPE_HOME, Constants.ATTR_TYPE_FAX));
             break;
         case Phone.TYPE_FAX_WORK:
-            appendTypeAttributes(builder, Arrays.asList(
-                    Constants.ATTR_TYPE_WORK, Constants.ATTR_TYPE_FAX));
+            attributeList.addAll(
+                    Arrays.asList(Constants.ATTR_TYPE_WORK, Constants.ATTR_TYPE_FAX));
             break;
         case Phone.TYPE_MOBILE:
-            builder.append(Constants.ATTR_TYPE_CELL);
+            attributeList.add(Constants.ATTR_TYPE_CELL);
             break;
         case Phone.TYPE_PAGER:
             if (mIsDoCoMo) {
                 // Not sure about the reason, but previous implementation had
                 // used "VOICE" instead of "PAGER"
-                // Also, refrain from using appendType() so that "TYPE=" is never be appended.
-                builder.append(Constants.ATTR_TYPE_VOICE);
+                attributeList.add(Constants.ATTR_TYPE_VOICE);
             } else {
-                appendTypeAttribute(builder, Constants.ATTR_TYPE_PAGER);
+                attributeList.add(Constants.ATTR_TYPE_PAGER);
             }
             break;
         case Phone.TYPE_OTHER:
-            appendTypeAttribute(builder, Constants.ATTR_TYPE_VOICE);
+            attributeList.add(Constants.ATTR_TYPE_VOICE);
+            break;
+        case Phone.TYPE_CAR:
+            attributeList.add(Constants.ATTR_TYPE_CAR);
+            break;
+        case Phone.TYPE_COMPANY_MAIN:
+            // There's no relevant field in vCard (at least 2.1).
+            attributeList.add(Constants.ATTR_TYPE_WORK);
+            isPrimary = true;
+            break;
+        case Phone.TYPE_ISDN:
+            attributeList.add(Constants.ATTR_TYPE_ISDN);
+            break;
+        case Phone.TYPE_MAIN:
+            isPrimary = true;
+            break;
+        case Phone.TYPE_OTHER_FAX:
+            attributeList.add(Constants.ATTR_TYPE_FAX);
+            break;
+        case Phone.TYPE_TELEX:
+            attributeList.add(Constants.ATTR_TYPE_TLX);
+            break;
+        case Phone.TYPE_WORK_MOBILE:
+            attributeList.addAll(
+                    Arrays.asList(Constants.ATTR_TYPE_WORK, Constants.ATTR_TYPE_CELL));
+            break;
+        case Phone.TYPE_WORK_PAGER:
+            attributeList.add(Constants.ATTR_TYPE_WORK);
+            // See above.
+            if (mIsDoCoMo) {
+                attributeList.add(Constants.ATTR_TYPE_VOICE);
+            } else {
+                attributeList.add(Constants.ATTR_TYPE_PAGER);
+            }
+            break;
+        case Phone.TYPE_MMS:
+            attributeList.add(Constants.ATTR_TYPE_MSG);
             break;
         case Phone.TYPE_CUSTOM:
             if (mUsesAndroidProperty && !TextUtils.isEmpty(label)
                         && VCardUtils.containsOnlyAlphaDigitHyphen(label)) {
-                appendTypeAttribute(builder, "X-" + label);
+                // Note: Strictly, vCard 2.1 does not allow "X-" attribute without
+                //       "TYPE=" string.
+                attributeList.add("X-" + label);
             } else {
                 // Just ignore the custom type.
-                appendTypeAttribute(builder, Constants.ATTR_TYPE_VOICE);
+                attributeList.add(Constants.ATTR_TYPE_VOICE);
             }
             break;
+        case Phone.TYPE_RADIO:
+        case Phone.TYPE_TTY_TDD:
         default:
-            appendUncommonPhoneType(builder, typeAsPrimitive);
             break;
         }
 
+        if (isPrimary) {
+            attributeList.add(Constants.ATTR_TYPE_PREF);
+        }
+
+        if (attributeList.isEmpty()) {
+            appendUncommonPhoneType(builder, typeAsPrimitive);
+        } else {
+            appendTypeAttributes(builder, attributeList);
+        }
+
         builder.append(VCARD_DATA_SEPARATOR);
         builder.append(encodedData);
         builder.append(VCARD_COL_SEPARATOR);
@@ -1711,15 +1963,43 @@
         }
     }
 
+    private void appendVCardLineWithCharsetAndQPDetection(final StringBuilder builder,
+            final String propertyName, final String rawData) {
+        appendVCardLineWithCharsetAndQPDetection(builder, propertyName, null, rawData);
+    }
+
+    private void appendVCardLineWithCharsetAndQPDetection(final StringBuilder builder,
+            final String propertyName,
+            final List<String> attributeList, final String rawData) {
+        final boolean needCharset =
+            (mUsesQuotedPrintable && !VCardUtils.containsOnlyPrintableAscii(rawData));
+        final boolean reallyUseQuotedPrintable =
+            !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawData);
+        appendVCardLine(builder, propertyName, attributeList,
+                rawData, needCharset, reallyUseQuotedPrintable);
+    }
+
     private void appendVCardLine(final StringBuilder builder,
             final String propertyName, final String rawData) {
         appendVCardLine(builder, propertyName, rawData, false, false);
     }
 
     private void appendVCardLine(final StringBuilder builder,
-            final String field, final String rawData, final boolean needCharset,
+            final String propertyName, final String rawData, final boolean needCharset,
             boolean needQuotedPrintable) {
-        builder.append(field);
+        appendVCardLine(builder, propertyName, null, rawData, needCharset, needQuotedPrintable);
+    }
+
+    private void appendVCardLine(final StringBuilder builder,
+            final String propertyName,
+            final List<String> attributeList,
+            final String rawData, final boolean needCharset,
+            boolean needQuotedPrintable) {
+        builder.append(propertyName);
+        if (attributeList != null && attributeList.size() > 0) {
+            builder.append(VCARD_ATTR_SEPARATOR);
+            appendTypeAttributes(builder, attributeList);
+        }
         if (needCharset) {
             builder.append(VCARD_ATTR_SEPARATOR);
             builder.append(mVCardAttributeCharset);
@@ -1741,6 +2021,9 @@
         builder.append(VCARD_COL_SEPARATOR);
     }
 
+    /**
+     * VCARD_ATTR_SEPARATOR must be appended before this method being called.
+     */
     private void appendTypeAttributes(final StringBuilder builder,
             final List<String> types) {
         // We may have to make this comma separated form like "TYPE=DOM,WORK" in the future,
@@ -1756,9 +2039,15 @@
         }
     }
 
+    /**
+     * VCARD_ATTR_SEPARATOR must be appended before this method being called.
+     */
     private void appendTypeAttribute(final StringBuilder builder, final String type) {
+        // Refrain from using appendType() so that "TYPE=" is not be appended when the
+        // device is DoCoMo's (just for safety).
+        //
         // Note: In vCard 3.0, Type strings also can be like this: "TYPE=HOME,PREF"
-        if (mIsV30 || mAppendTypeParamName) {
+        if ((mIsV30 || mAppendTypeParamName) && !mIsDoCoMo) {
             builder.append(Constants.ATTR_TYPE).append(VCARD_ATTR_EQUAL);
         }
         builder.append(type);
@@ -1869,12 +2158,11 @@
         if (!(VCardUtils.containsOnlyPrintableAscii(phoneName))) {
             needCharset = true;
         }
-        // TODO: QP should be used? Using mUsesQPToPrimaryProperties should help.
         appendVCardLine(builder, Constants.PROPERTY_FN, phoneName, needCharset, false);
         appendVCardLine(builder, Constants.PROPERTY_N, phoneName, needCharset, false);
 
         String label = Integer.toString(phonetype);
-        appendVCardTelephoneLine(builder, phonetype, label, phoneNumber);
+        appendVCardTelephoneLine(builder, phonetype, label, phoneNumber, false);
 
         appendVCardLine(builder, Constants.PROPERTY_END, VCARD_DATA_VCARD);
 
@@ -1948,7 +2236,6 @@
             name = mCursor.getString(NUMBER_COLUMN_INDEX);
         }
         final boolean needCharset = !(VCardUtils.containsOnlyPrintableAscii(name));
-        // TODO: QP should be used? Using mUsesQPToPrimaryProperties should help.
         appendVCardLine(builder, Constants.PROPERTY_FN, name, needCharset, false);
         appendVCardLine(builder, Constants.PROPERTY_N, name, needCharset, false);
 
@@ -1958,7 +2245,7 @@
         if (TextUtils.isEmpty(label)) {
             label = Integer.toString(type);
         }
-        appendVCardTelephoneLine(builder, type, label, number);
+        appendVCardTelephoneLine(builder, type, label, number, false);
         tryAppendCallHistoryTimeStampField(builder);
         appendVCardLine(builder, Constants.PROPERTY_END, VCARD_DATA_VCARD);
         return builder.toString();
diff --git a/core/java/android/pim/vcard/VCardConfig.java b/core/java/android/pim/vcard/VCardConfig.java
index 03ed329..9581c74 100644
--- a/core/java/android/pim/vcard/VCardConfig.java
+++ b/core/java/android/pim/vcard/VCardConfig.java
@@ -15,14 +15,20 @@
  */
 package android.pim.vcard;
 
+import android.util.Log;
+
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * The class representing VCard related configurations. Useful static methods are not in this class
  * but in VCardUtils.
  */
 public class VCardConfig {
+    private static final String LOG_TAG = "vcard.VCardConfig";
+
     // TODO: may be better to make the instance of this available and stop using static methods and
     //        one integer. 
 
@@ -95,18 +101,63 @@
     private static final int FLAG_DOCOMO = 0x20000000;
 
     /**
-     * The flag indicating the vCard composer use Quoted-Printable toward even "primary" types.
-     * In this context, "primary" types means "N", "FN", etc. which are usually "not" encoded
-     * into Quoted-Printable format in external exporters.
-     * This flag is useful when some target importer does not accept "primary" property values
-     * without Quoted-Printable encoding.
-     *
-     * @hide Temporaly made public. We don't strictly define "primary", so we may change the
-     * behavior around this flag in the future. Do not use this flag without any reason.
+     * <P>
+     * The flag indicating the vCard composer does "NOT" use Quoted-Printable toward "primary"
+     * properties even though it is required by vCard 2.1 (QP is prohibited in vCard 3.0).
+     * </P>
+     * <P>
+     * We actually cannot define what is the "primary" property. Note that this is NOT defined
+     * in vCard specification either. Also be aware that it is NOT related to "primary" notion
+     * used in {@link android.provider.ContactsContract}.
+     * This notion is just for vCard composition in Android.
+     * </P>
+     * <P>
+     * We added this Android-specific notion since some (incomplete) vCard exporters for vCard 2.1
+     * do NOT use Quoted-Printable encoding toward some properties like "N", "FN", etc. even when
+     * their values contain non-ascii or/and CR/LF, while they use the encoding in the other
+     * properties like "ADR", "ORG", etc.
+     * <P>
+     * We are afraid of the case where some vCard importer also forget handling QP presuming QP is
+     * not used in such fields.
+     * </P>
+     * <P>
+     * This flag is useful when some target importer you are going to focus on does not accept
+     * such "primary" property values with Quoted-Printable encoding.
+     * </P>
+     * <P>
+     * Again, we should not use this flag at all for complying vCard 2.1 spec.
+     * </P>
+     * <P>
+     * We will change the behavior around this flag in the future, after understanding the other
+     * real vCard cases around this problem. Please use this flag with extreme caution even when
+     * needed.
+     * </P>
+     * <P>
+     * In vCard 3.0, Quoted-Printable is explicitly "prohibitted", so we don't need to care this
+     * kind of problem (hopefully).
+     * </P>
      */
-    public static final int FLAG_USE_QP_TO_PRIMARY_PROPERTIES = 0x10000000;
+    public static final int FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES = 0x10000000;
 
     /**
+     * <P>
+     * The flag indicating that phonetic name related fields must be converted to
+     * appropriate form. Note that "appropriate" is not defined in any vCard specification.
+     * This is Android-specific.
+     * </P>
+     * <P>
+     * One typical (and currently sole) example where we need this flag is the time when
+     * we need to emit Japanese phonetic names into vCard entries. The property values
+     * should be encoded into half-width katakana when the target importer is Japanese mobile
+     * phones', which are probably not able to parse full-width hiragana/katakana for
+     * historical reasons, while the vCard importers embedded to softwares for PC should be
+     * able to parse them as we expect.
+     * </P>
+     */
+    public static final int FLAG_CONVERT_PHONETIC_NAME_STRINGS = 0x0800000;
+
+    /**
+     * <P>
      * The flag indicating the vCard composer "for 2.1" emits "TYPE=" string every time
      * possible. The default behavior does not emit it and is valid, while adding "TYPE="
      * is also valid. In vCrad 3.0, this flag is unnecessary, since "TYPE=" is MUST in
@@ -119,87 +170,118 @@
      *
      * e.g. int vcardType = (VCARD_TYPE_V21_GENERIC | FLAG_APPEND_TYPE_PARAM);
      */
-    public static final int FLAG_APPEND_TYPE_PARAM = 0x08000000;
+    public static final int FLAG_APPEND_TYPE_PARAM = 0x04000000;
 
     //// The followings are VCard types available from importer/exporter. ////
 
     /**
+     * <P>
      * General vCard format with the version 2.1. Uses UTF-8 for the charset.
-     * When composing a vCard entry, the US convension will be used.
-     * 
+     * When composing a vCard entry, the US convension will be used toward formatting
+     * some values
+     * </P>
+     * <P>
      * e.g. The order of the display name would be "Prefix Given Middle Family Suffix",
-     * while in Japan, it should be "Prefix Family Middle Given Suffix".
+     * while it should be "Prefix Family Middle Given Suffix" in Japan.
+     * </P>
      */
-    public static final int VCARD_TYPE_V21_GENERIC =
+    public static final int VCARD_TYPE_V21_GENERIC_UTF8 =
         (FLAG_V21 | NAME_ORDER_DEFAULT | FLAG_CHARSET_UTF8 |
                 FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
 
-    /* package */ static String VCARD_TYPE_V21_GENERIC_STR = "v21_generic";
+    /* package */ static String VCARD_TYPE_V21_GENERIC_UTF8_STR = "v21_generic";
     
     /**
+     * <P>
      * General vCard format with the version 3.0. Uses UTF-8 for the charset.
-     * 
-     * Note that this type is not fully implemented, so probably some bugs remain both in
-     * parsing and composing.
-     *
-     * TODO: implement this type correctly.
+     * </P>
+     * <P>
+     * Not ready yet. Use with caution when you use this.
+     * </P>
      */
-    public static final int VCARD_TYPE_V30_GENERIC =
+    public static final int VCARD_TYPE_V30_GENERIC_UTF8 =
         (FLAG_V30 | NAME_ORDER_DEFAULT | FLAG_CHARSET_UTF8 |
                 FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
 
-    /* package */ static final String VCARD_TYPE_V30_GENERIC_STR = "v30_generic";
+    /* package */ static final String VCARD_TYPE_V30_GENERIC_UTF8_STR = "v30_generic";
     
     /**
-     * General vCard format with the version 2.1 with some Europe convension. Uses Utf-8.
+     * <P>
+     * General vCard format for the vCard 2.1 with some Europe convension. Uses Utf-8.
      * Currently, only name order is considered ("Prefix Middle Given Family Suffix")
+     * </P>
      */
-    public static final int VCARD_TYPE_V21_EUROPE =
+    public static final int VCARD_TYPE_V21_EUROPE_UTF8 =
         (FLAG_V21 | NAME_ORDER_EUROPE | FLAG_CHARSET_UTF8 |
                 FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
     
-    /* package */ static final String VCARD_TYPE_V21_EUROPE_STR = "v21_europe";
+    /* package */ static final String VCARD_TYPE_V21_EUROPE_UTF8_STR = "v21_europe";
     
     /**
+     * <P>
      * General vCard format with the version 3.0 with some Europe convension. Uses UTF-8
+     * </P>
+     * <P>
+     * Not ready yet. Use with caution when you use this.
+     * </P>
      */
-    public static final int VCARD_TYPE_V30_EUROPE =
+    public static final int VCARD_TYPE_V30_EUROPE_UTF8 =
         (FLAG_V30 | NAME_ORDER_EUROPE | FLAG_CHARSET_UTF8 |
                 FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
     
     /* package */ static final String VCARD_TYPE_V30_EUROPE_STR = "v30_europe";
-    
-    /**
-     * vCard 2.1 format for miscellaneous Japanese devices. Shift_Jis is used for
-     * parsing/composing the vCard data.
-     */
-    public static final int VCARD_TYPE_V21_JAPANESE =
-        (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS | 
-                FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
 
-    /* package */ static final String VCARD_TYPE_V21_JAPANESE_STR = "v21_japanese";
-    
     /**
-     * vCard 2.1 format for miscellaneous Japanese devices, using UTF-8 as default charset.
+     * <P>
+     * The vCard 2.1 format for miscellaneous Japanese devices, using UTF-8 as default charset.
+     * </P>
+     * <P>
+     * Not ready yet. Use with caution when you use this.
+     * </P>
      */
     public static final int VCARD_TYPE_V21_JAPANESE_UTF8 =
         (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_UTF8 |
                 FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
 
     /* package */ static final String VCARD_TYPE_V21_JAPANESE_UTF8_STR = "v21_japanese_utf8";
+
+    /**
+     * <P>
+     * vCard 2.1 format for miscellaneous Japanese devices. Shift_Jis is used for
+     * parsing/composing the vCard data.
+     * </P>
+     * <P>
+     * Not ready yet. Use with caution when you use this.
+     * </P>
+     */
+    public static final int VCARD_TYPE_V21_JAPANESE_SJIS =
+        (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS |
+                FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
+
+    /* package */ static final String VCARD_TYPE_V21_JAPANESE_SJIS_STR = "v21_japanese_sjis";
     
     /**
+     * <P>
      * vCard format for miscellaneous Japanese devices, using Shift_Jis for
      * parsing/composing the vCard data.
+     * </P>
+     * <P>
+     * Not ready yet. Use with caution when you use this.
+     * </P>
      */
-    public static final int VCARD_TYPE_V30_JAPANESE =
+    public static final int VCARD_TYPE_V30_JAPANESE_SJIS =
         (FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS |
                 FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
         
-    /* package */ static final String VCARD_TYPE_V30_JAPANESE_STR = "v30_japanese";
+    /* package */ static final String VCARD_TYPE_V30_JAPANESE_SJIS_STR = "v30_japanese_sjis";
     
     /**
-     * vCard 3.0 format for miscellaneous Japanese devices, using UTF-8 as default charset.
+     * <P>
+     * The vCard 3.0 format for miscellaneous Japanese devices, using UTF-8 as default charset.
+     * </P>
+     * <P>
+     * Not ready yet. Use with caution when you use this.
+     * </P>
      */
     public static final int VCARD_TYPE_V30_JAPANESE_UTF8 =
         (FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_CHARSET_UTF8 |
@@ -208,38 +290,72 @@
     /* package */ static final String VCARD_TYPE_V30_JAPANESE_UTF8_STR = "v30_japanese_utf8";
 
     /**
-     *  VCard format used in DoCoMo, which is one of Japanese mobile phone careers.
-     *  Base version is vCard 2.1, but the data has several DoCoMo-specific convensions.
-     *  No Android-specific property nor defact property is included.
+     * <P>
+     * The vCard 2.1 based format which (partially) considers the convention in Japanese
+     * mobile phones, where phonetic names are translated to half-width katakana if
+     * possible, etc.
+     * </P>
+     * <P>
+     * Not ready yet. Use with caution when you use this.
+     * </P>
+     */
+    public static final int VCARD_TYPE_V21_JAPANESE_MOBILE =
+        (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS |
+                FLAG_CONVERT_PHONETIC_NAME_STRINGS |
+                FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES);
+
+    public static final String VCARD_TYPE_V21_JAPANESE_MOBILE_STR = "v21_japanese_mobile";
+
+    /**
+     * <P>
+     * VCard format used in DoCoMo, which is one of Japanese mobile phone careers.
+     * </p>
+     * <P>
+     * Base version is vCard 2.1, but the data has several DoCoMo-specific convensions.
+     * No Android-specific property nor defact property is included. The "Primary" properties
+     * are NOT encoded to Quoted-Printable.
+     * </P>
      */
     public static final int VCARD_TYPE_DOCOMO =
-        (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS | FLAG_DOCOMO);
+        (VCARD_TYPE_V21_JAPANESE_MOBILE | FLAG_DOCOMO);
 
     private static final String VCARD_TYPE_DOCOMO_STR = "docomo";
     
-    public static int VCARD_TYPE_DEFAULT = VCARD_TYPE_V21_GENERIC;
+    public static int VCARD_TYPE_DEFAULT = VCARD_TYPE_V21_GENERIC_UTF8;
 
-    private static final Map<String, Integer> VCARD_TYPES_MAP;
+    private static final Map<String, Integer> sVCardTypeMap;
+    private static final Set<Integer> sJapaneseMobileTypeSet;
     
     static {
-        VCARD_TYPES_MAP = new HashMap<String, Integer>();
-        VCARD_TYPES_MAP.put(VCARD_TYPE_V21_GENERIC_STR, VCARD_TYPE_V21_GENERIC);
-        VCARD_TYPES_MAP.put(VCARD_TYPE_V30_GENERIC_STR, VCARD_TYPE_V30_GENERIC);
-        VCARD_TYPES_MAP.put(VCARD_TYPE_V21_EUROPE_STR, VCARD_TYPE_V21_EUROPE);
-        VCARD_TYPES_MAP.put(VCARD_TYPE_V30_EUROPE_STR, VCARD_TYPE_V30_EUROPE);
-        VCARD_TYPES_MAP.put(VCARD_TYPE_V21_JAPANESE_STR, VCARD_TYPE_V21_JAPANESE);
-        VCARD_TYPES_MAP.put(VCARD_TYPE_V21_JAPANESE_UTF8_STR, VCARD_TYPE_V21_JAPANESE_UTF8);
-        VCARD_TYPES_MAP.put(VCARD_TYPE_V30_JAPANESE_STR, VCARD_TYPE_V30_JAPANESE);
-        VCARD_TYPES_MAP.put(VCARD_TYPE_V30_JAPANESE_UTF8_STR, VCARD_TYPE_V30_JAPANESE_UTF8);
-        VCARD_TYPES_MAP.put(VCARD_TYPE_DOCOMO_STR, VCARD_TYPE_DOCOMO);
+        sVCardTypeMap = new HashMap<String, Integer>();
+        sVCardTypeMap.put(VCARD_TYPE_V21_GENERIC_UTF8_STR, VCARD_TYPE_V21_GENERIC_UTF8);
+        sVCardTypeMap.put(VCARD_TYPE_V30_GENERIC_UTF8_STR, VCARD_TYPE_V30_GENERIC_UTF8);
+        sVCardTypeMap.put(VCARD_TYPE_V21_EUROPE_UTF8_STR, VCARD_TYPE_V21_EUROPE_UTF8);
+        sVCardTypeMap.put(VCARD_TYPE_V30_EUROPE_STR, VCARD_TYPE_V30_EUROPE_UTF8);
+        sVCardTypeMap.put(VCARD_TYPE_V21_JAPANESE_SJIS_STR, VCARD_TYPE_V21_JAPANESE_SJIS);
+        sVCardTypeMap.put(VCARD_TYPE_V21_JAPANESE_UTF8_STR, VCARD_TYPE_V21_JAPANESE_UTF8);
+        sVCardTypeMap.put(VCARD_TYPE_V30_JAPANESE_SJIS_STR, VCARD_TYPE_V30_JAPANESE_SJIS);
+        sVCardTypeMap.put(VCARD_TYPE_V30_JAPANESE_UTF8_STR, VCARD_TYPE_V30_JAPANESE_UTF8);
+        sVCardTypeMap.put(VCARD_TYPE_V21_JAPANESE_MOBILE_STR, VCARD_TYPE_V21_JAPANESE_MOBILE);
+        sVCardTypeMap.put(VCARD_TYPE_DOCOMO_STR, VCARD_TYPE_DOCOMO);
+
+        sJapaneseMobileTypeSet = new HashSet<Integer>();
+        sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE_SJIS);
+        sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE_UTF8);
+        sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE_SJIS);
+        sJapaneseMobileTypeSet.add(VCARD_TYPE_V30_JAPANESE_SJIS);
+        sJapaneseMobileTypeSet.add(VCARD_TYPE_V30_JAPANESE_UTF8);
+        sJapaneseMobileTypeSet.add(VCARD_TYPE_V21_JAPANESE_MOBILE);
+        sJapaneseMobileTypeSet.add(VCARD_TYPE_DOCOMO);
     }
 
     public static int getVCardTypeFromString(String vcardTypeString) {
         String loweredKey = vcardTypeString.toLowerCase();
-        if (VCARD_TYPES_MAP.containsKey(loweredKey)) {
-            return VCARD_TYPES_MAP.get(loweredKey);
+        if (sVCardTypeMap.containsKey(loweredKey)) {
+            return sVCardTypeMap.get(loweredKey);
         } else {
             // XXX: should return the value indicating the input is invalid?
+            Log.e(LOG_TAG, "Unknown vCard type String: \"" + vcardTypeString + "\"");
             return VCARD_TYPE_DEFAULT;
         }
     }
@@ -252,22 +368,6 @@
         return !isV30(vcardType);
     }
 
-    public static boolean isDoCoMo(int vcardType) {
-        return ((vcardType & FLAG_DOCOMO) != 0);
-    }
-    
-    /**
-     * @return true if the device is Japanese and some Japanese convension is
-     * applied to creating "formatted" something like FORMATTED_ADDRESS.
-     */
-    public static boolean isJapaneseDevice(int vcardType) {
-        return ((vcardType == VCARD_TYPE_V21_JAPANESE) ||
-                (vcardType == VCARD_TYPE_V21_JAPANESE_UTF8) ||
-                (vcardType == VCARD_TYPE_V30_JAPANESE) ||
-                (vcardType == VCARD_TYPE_V30_JAPANESE_UTF8) ||
-                (vcardType == VCARD_TYPE_DOCOMO));
-    }
-
     public static boolean usesUtf8(int vcardType) {
         return ((vcardType & FLAG_CHARSET_UTF8) != 0);
     }
@@ -276,17 +376,6 @@
         return ((vcardType & FLAG_CHARSET_SHIFT_JIS) != 0);
     }
     
-    /**
-     * @return true when Japanese phonetic string must be converted to a string
-     * containing only half-width katakana. This method exists since Japanese mobile
-     * phones usually use only half-width katakana for expressing phonetic names and
-     * some devices are not ready for parsing other phonetic strings like hiragana and
-     * full-width katakana.
-     */
-    public static boolean needsToConvertPhoneticString(int vcardType) {
-        return (vcardType == VCARD_TYPE_DOCOMO);
-    }
-
     public static int getNameOrderType(int vcardType) {
         return vcardType & NAME_ORDER_MASK;
     }
@@ -299,24 +388,37 @@
         return ((vcardType & FLAG_USE_DEFACT_PROPERTY) != 0);
     }
 
-    public static boolean onlyOneNoteFieldIsAvailable(int vcardType) {
-        return vcardType == VCARD_TYPE_DOCOMO;
-    }
-
     public static boolean showPerformanceLog() {
         return (VCardConfig.LOG_LEVEL & VCardConfig.LOG_LEVEL_PERFORMANCE_MEASUREMENT) != 0;
     }
 
-    /**
-     * @hide
-     */
-    public static boolean usesQPToPrimaryProperties(int vcardType) {
-       return (usesQuotedPrintable(vcardType) &&
-               ((vcardType & FLAG_USE_QP_TO_PRIMARY_PROPERTIES) != 0));
+    public static boolean refrainsQPToPrimaryProperties(int vcardType) {
+       return (!usesQuotedPrintable(vcardType) ||
+               ((vcardType & FLAG_REFRAIN_QP_TO_PRIMARY_PROPERTIES) != 0));
     }
 
     public static boolean appendTypeParamName(int vcardType) {
-        return (vcardType & FLAG_APPEND_TYPE_PARAM) != 0;
+        return (isV30(vcardType) || ((vcardType & FLAG_APPEND_TYPE_PARAM) != 0));
+    }
+
+    /**
+     * @return true if the device is Japanese and some Japanese convension is
+     * applied to creating "formatted" something like FORMATTED_ADDRESS.
+     */
+    public static boolean isJapaneseDevice(int vcardType) {
+        return sJapaneseMobileTypeSet.contains(vcardType);
+    }
+
+    public static boolean needsToConvertPhoneticString(int vcardType) {
+        return ((vcardType & FLAG_CONVERT_PHONETIC_NAME_STRINGS) != 0);
+    }
+
+    public static boolean onlyOneNoteFieldIsAvailable(int vcardType) {
+        return vcardType == VCARD_TYPE_DOCOMO;
+    }
+
+    public static boolean isDoCoMo(int vcardType) {
+        return ((vcardType & FLAG_DOCOMO) != 0);
     }
 
     private VCardConfig() {
diff --git a/core/java/android/pim/vcard/VCardDataBuilder.java b/core/java/android/pim/vcard/VCardDataBuilder.java
index d00f616..76ad482 100644
--- a/core/java/android/pim/vcard/VCardDataBuilder.java
+++ b/core/java/android/pim/vcard/VCardDataBuilder.java
@@ -69,7 +69,7 @@
     private List<EntryHandler> mEntryHandlers = new ArrayList<EntryHandler>();
     
     public VCardDataBuilder() {
-        this(null, null, false, VCardConfig.VCARD_TYPE_V21_GENERIC, null);
+        this(null, null, false, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8, null);
     }
 
     /**
diff --git a/core/java/android/pim/vcard/VCardUtils.java b/core/java/android/pim/vcard/VCardUtils.java
index b3bf426..376327c 100644
--- a/core/java/android/pim/vcard/VCardUtils.java
+++ b/core/java/android/pim/vcard/VCardUtils.java
@@ -18,6 +18,7 @@
 import android.content.ContentProviderOperation;
 import android.content.ContentValues;
 import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.CommonDataKinds.Im;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.text.TextUtils;
@@ -44,38 +45,49 @@
     private static final Map<Integer, String> sKnownPhoneTypesMap_ItoS;
     private static final Set<String> sPhoneTypesSetUnknownToContacts;
 
-    private static final Map<String, Integer> sKnownPhoneTypesMap_StoI;
+    private static final Map<String, Integer> sKnownPhoneTypeMap_StoI;
+
+    private static final Map<Integer, String> sKnownImPropNameMap_ItoS;
 
     static {
         sKnownPhoneTypesMap_ItoS = new HashMap<Integer, String>();
-        sKnownPhoneTypesMap_StoI = new HashMap<String, Integer>();
+        sKnownPhoneTypeMap_StoI = new HashMap<String, Integer>();
 
         sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_CAR, Constants.ATTR_TYPE_CAR);
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_CAR, Phone.TYPE_CAR);
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_CAR, Phone.TYPE_CAR);
         sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_PAGER, Constants.ATTR_TYPE_PAGER);
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_PAGER, Phone.TYPE_PAGER);
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_PAGER, Phone.TYPE_PAGER);
         sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_ISDN, Constants.ATTR_TYPE_ISDN);
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_ISDN, Phone.TYPE_ISDN);
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_ISDN, Phone.TYPE_ISDN);
         
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_HOME, Phone.TYPE_HOME);
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_WORK, Phone.TYPE_WORK);
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_TYPE_CELL, Phone.TYPE_MOBILE);
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_HOME, Phone.TYPE_HOME);
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_WORK, Phone.TYPE_WORK);
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_TYPE_CELL, Phone.TYPE_MOBILE);
                 
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_OTHER, Phone.TYPE_OTHER);
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_CALLBACK, Phone.TYPE_CALLBACK);
-        sKnownPhoneTypesMap_StoI.put(
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_OTHER, Phone.TYPE_OTHER);
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_CALLBACK, Phone.TYPE_CALLBACK);
+        sKnownPhoneTypeMap_StoI.put(
                 Constants.ATTR_PHONE_EXTRA_TYPE_COMPANY_MAIN, Phone.TYPE_COMPANY_MAIN);
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_RADIO, Phone.TYPE_RADIO);
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_TELEX, Phone.TYPE_TELEX);
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_TTY_TDD, Phone.TYPE_TTY_TDD);
-        sKnownPhoneTypesMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_ASSISTANT,
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_RADIO, Phone.TYPE_RADIO);
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_TTY_TDD, Phone.TYPE_TTY_TDD);
+        sKnownPhoneTypeMap_StoI.put(Constants.ATTR_PHONE_EXTRA_TYPE_ASSISTANT,
                 Phone.TYPE_ASSISTANT);
 
         sPhoneTypesSetUnknownToContacts = new HashSet<String>();
         sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_MODEM);
-        sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_MSG);
         sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_BBS);
         sPhoneTypesSetUnknownToContacts.add(Constants.ATTR_TYPE_VIDEO);
+
+        sKnownImPropNameMap_ItoS = new HashMap<Integer, String>();
+        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_AIM, Constants.PROPERTY_X_AIM);
+        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_MSN, Constants.PROPERTY_X_MSN);
+        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_YAHOO, Constants.PROPERTY_X_YAHOO);
+        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_SKYPE, Constants.PROPERTY_X_SKYPE_USERNAME);
+        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_GOOGLE_TALK, Constants.PROPERTY_X_GOOGLE_TALK);
+        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_ICQ, Constants.PROPERTY_X_ICQ);
+        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_JABBER, Constants.PROPERTY_X_JABBER);
+        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_QQ, Constants.PROPERTY_X_QQ);
+        sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_NETMEETING, Constants.PROPERTY_X_NETMEETING);
     }
 
     public static String getPhoneAttributeString(Integer type) {
@@ -103,7 +115,7 @@
                     if (typeString.startsWith("X-") && type < 0) {
                         typeString = typeString.substring(2);
                     }
-                    Integer tmp = sKnownPhoneTypesMap_StoI.get(typeString);
+                    Integer tmp = sKnownPhoneTypeMap_StoI.get(typeString);
                     if (tmp != null) {
                         type = tmp;
                     } else if (type < 0) {
@@ -136,7 +148,11 @@
             return type;
         }
     }
-    
+
+    public static String getPropertyNameForIm(int protocol) {
+        return sKnownImPropNameMap_ItoS.get(protocol);
+    }
+
     public static boolean isValidPhoneAttribute(String phoneAttribute, int vcardType) {
         // TODO: check the following.
         // - it may violate vCard spec
@@ -206,12 +222,12 @@
             builder.withValue(Data.IS_PRIMARY, 1);
         }
     }
-    
+
     /**
      * Returns String[] containing address information based on vCard spec
      * (PO Box, Extended Address, Street, Locality, Region, Postal Code, Country Name).
      * All String objects are non-null ("" is used when the relevant data is empty).
-     * 
+     *
      * Note that the data structure of ContactsContract is different from that defined in vCard.
      * So some conversion may be performed in this method. See also
      * {{@link #insertStructuredPostalDataUsingContactsStruct(int,
@@ -219,13 +235,20 @@
      * android.pim.vcard.ContactStruct.PostalData)}
      */
     public static String[] getVCardPostalElements(ContentValues contentValues) {
+        // adr-value    = 0*6(text-value ";") text-value
+        //              ; PO Box, Extended Address, Street, Locality, Region, Postal
+        //              ; Code, Country Name
         String[] dataArray = new String[7];
         dataArray[0] = contentValues.getAsString(StructuredPostal.POBOX);
         if (dataArray[0] == null) {
             dataArray[0] = "";
         }
-        // Extended addr. There's no relevant data in ContactsContract.
-        dataArray[1] = "";
+        // We keep all the data in StructuredPostal, presuming NEIGHBORHOOD is
+        // similar to "Extended Address".
+        dataArray[1] = contentValues.getAsString(StructuredPostal.NEIGHBORHOOD);
+        if (dataArray[1] == null) {
+            dataArray[1] = "";
+        }
         dataArray[2] = contentValues.getAsString(StructuredPostal.STREET);
         if (dataArray[2] == null) {
             dataArray[2] = "";
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index f046cef..faa63af 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -514,6 +514,12 @@
          * <P>Type: String</P>
          */
         public static final String OWNER_ACCOUNT = "ownerAccount";
+
+        /**
+         * Whether the row has been deleted.  A deleted row should be ignored.
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String DELETED = "deleted";
     }
 
     /**
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 5ea6539..7904401 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -129,7 +129,7 @@
      * these columns are private to the sync adapter. Other clients of the API
      * should not attempt to either read or write this column.
      */
-    private interface BaseSyncColumns {
+    protected interface BaseSyncColumns {
 
         /** Generic column for use by sync adapters. */
         public static final String SYNC1 = "sync1";
@@ -145,7 +145,7 @@
      * Columns that appear when each row of a table belongs to a specific
      * account, including sync information that an account may need.
      */
-    private interface SyncColumns extends BaseSyncColumns {
+    protected interface SyncColumns extends BaseSyncColumns {
         /**
          * The name of the account instance to which this row belongs, which when paired with
          * {@link #ACCOUNT_TYPE} identifies a specific account.
@@ -181,7 +181,7 @@
         public static final String DIRTY = "dirty";
     }
 
-    private interface ContactOptionsColumns {
+    protected interface ContactOptionsColumns {
         /**
          * The number of times a contact has been contacted
          * <P>Type: INTEGER</P>
@@ -214,7 +214,7 @@
         public static final String SEND_TO_VOICEMAIL = "send_to_voicemail";
     }
 
-    private interface ContactsColumns {
+    protected interface ContactsColumns {
         /**
          * The display name for the contact.
          * <P>Type: TEXT</P>
@@ -247,7 +247,7 @@
         public static final String LOOKUP_KEY = "lookup";
     }
 
-    private interface ContactStatusColumns {
+    protected interface ContactStatusColumns {
         /**
          * Contact presence status. See {@link StatusUpdates} for individual status
          * definitions.
@@ -540,7 +540,7 @@
         }
     }
 
-    private interface RawContactsColumns {
+    protected interface RawContactsColumns {
         /**
          * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} that this
          * data belongs to.
@@ -699,7 +699,7 @@
         }
     }
 
-    private interface StatusColumns extends Im.CommonPresenceColumns {
+    protected interface StatusColumns extends Im.CommonPresenceColumns {
         /**
          * Contact's latest presence level.
          * <P>Type: INTEGER (one of the values below)</P>
@@ -739,7 +739,7 @@
         public static final String STATUS_ICON = "status_icon";
     }
 
-    private interface DataColumns {
+    protected interface DataColumns {
         /**
          * The package name to use when creating {@link Resources} objects for
          * this data row. This value is only designed for use when building user
@@ -826,7 +826,7 @@
     /**
      * Combines all columns returned by {@link Data} table queries.
      */
-    private interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns,
+    protected interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns,
         RawContactsColumns, ContactsColumns, ContactOptionsColumns, ContactStatusColumns {
 
     }
@@ -938,7 +938,7 @@
         public static final String DATA_ID = "data_id";
     }
 
-    private interface PhoneLookupColumns {
+    protected interface PhoneLookupColumns {
         /**
          * The phone number as the user entered it.
          * <P>Type: TEXT</P>
@@ -986,7 +986,7 @@
      * Additional data mixed in with {@link StatusColumns} to link
      * back to specific {@link ContactsContract.Data#_ID} entries.
      */
-    private interface PresenceColumns {
+    protected interface PresenceColumns {
 
         /**
          * Reference to the {@link Data#_ID} entry that owns this presence.
@@ -1123,7 +1123,7 @@
         /**
          * Columns common across the specific types.
          */
-        private interface CommonColumns extends BaseTypes {
+        protected interface CommonColumns extends BaseTypes {
             /**
              * The data for the contact method.
              * <P>Type: TEXT</P>
@@ -1930,7 +1930,7 @@
         }
     }
 
-    private interface GroupsColumns {
+    protected interface GroupsColumns {
         /**
          * The display title of this group.
          * <p>
@@ -2117,7 +2117,7 @@
         public static final String RAW_CONTACT_ID2 = "raw_contact_id2";
     }
 
-    private interface SettingsColumns {
+    protected interface SettingsColumns {
         /**
          * The name of the account instance to which this row belongs.
          * <P>Type: TEXT</P>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8c9581d..456181c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1081,6 +1081,18 @@
         public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
 
         /**
+         * SCREEN_BRIGHTNESS_MODE value for manual mode.
+         * @hide
+         */
+        public static final int SCREEN_BRIGHTNESS_MODE_MANUAL = 0;
+
+        /**
+         * SCREEN_BRIGHTNESS_MODE value for manual mode.
+         * @hide
+         */
+        public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1;
+
+        /**
          * Control whether the process CPU usage meter should be shown.
          */
         public static final String SHOW_PROCESSES = "show_processes";
@@ -3098,6 +3110,13 @@
                 = "google_login_generic_auth_service";
 
         /**
+         * Duration in milliseconds after setup at which market does not reconcile applications
+         * which are installed during restore.
+         */
+        public static final String VENDING_RESTORE_WINDOW_MS = "vending_restore_window_ms";
+
+
+        /**
          * Frequency in milliseconds at which we should sync the locally installed Vending Machine
          * content with the server.
          */
@@ -3611,7 +3630,6 @@
          */
         public static final String SEARCH_PER_SOURCE_CONCURRENT_QUERY_LIMIT =
                 "search_per_source_concurrent_query_limit";
-
         /**
          * Flag for allowing ActivityManagerService to send ACTION_APP_ERROR intents
          * on application crashes and ANRs. If this is disabled, the crash/ANR dialog
@@ -3626,6 +3644,32 @@
         public static final String LAST_KMSG_KB = "last_kmsg_kb";
 
         /**
+         * Maximum age of entries kept by {@link android.os.IDropBox}.
+         */
+        public static final String DROPBOX_AGE_SECONDS =
+                "dropbox_age_seconds";
+        /**
+         * Maximum amount of disk space used by {@link android.os.IDropBox} no matter what.
+         */
+        public static final String DROPBOX_QUOTA_KB =
+                "dropbox_quota_kb";
+        /**
+         * Percent of free disk (excluding reserve) which {@link android.os.IDropBox} will use.
+         */
+        public static final String DROPBOX_QUOTA_PERCENT =
+                "dropbox_quota_percent";
+        /**
+         * Percent of total disk which {@link android.os.IDropBox} will never dip into.
+         */
+        public static final String DROPBOX_RESERVE_PERCENT =
+                "dropbox_reserve_percent";
+        /**
+         * Prefix for per-tag dropbox disable/enable settings.
+         */
+        public static final String DROPBOX_TAG_PREFIX =
+                "dropbox:";
+
+        /**
          * @deprecated
          * @hide
          */
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 9a2d6d9..ec3b2ff 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -72,8 +72,7 @@
     private final AudioManager mAudioManager;
     private final BluetoothService mBluetoothService;
     private final BluetoothAdapter mAdapter;
-    private boolean mSuspending;
-    private boolean mResuming;
+    private int   mTargetA2dpState;
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -151,8 +150,7 @@
 
         if (mBluetoothService.isEnabled())
             onBluetoothEnable();
-        mSuspending = false;
-        mResuming = false;
+        mTargetA2dpState = -1;
     }
 
     @Override
@@ -341,10 +339,7 @@
     public synchronized boolean suspendSink(BluetoothDevice device) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                             "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("suspendSink(" + device + "), mSuspending: "+mSuspending+", mResuming: "+mResuming);
-        if (mSuspending) {
-            return true;
-        }
+        if (DBG) log("suspendSink(" + device + "), mTargetA2dpState: "+mTargetA2dpState);
         if (device == null || mAudioDevices == null) {
             return false;
         }
@@ -353,28 +348,15 @@
         if (path == null || state == null) {
             return false;
         }
-        switch (state.intValue()) {
-        case BluetoothA2dp.STATE_CONNECTED:
-            if (mResuming) {
-                mSuspending = true;
-            }
-            return true;
-        case BluetoothA2dp.STATE_PLAYING:
-            mAudioManager.setParameters("A2dpSuspended=true");
-            mSuspending = suspendSinkNative(path);
-            return mSuspending;
-        default:
-            return false;
-        }
+
+        mTargetA2dpState = BluetoothA2dp.STATE_CONNECTED;
+        return checkSinkSuspendState(state.intValue());
     }
 
     public synchronized boolean resumeSink(BluetoothDevice device) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                             "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("resumeSink(" + device + "), mResuming: "+mResuming+", mSuspending: "+mSuspending);
-        if (mResuming) {
-            return true;
-        }
+        if (DBG) log("resumeSink(" + device + "), mTargetA2dpState: "+mTargetA2dpState);
         if (device == null || mAudioDevices == null) {
             return false;
         }
@@ -383,19 +365,8 @@
         if (path == null || state == null) {
             return false;
         }
-        switch (state.intValue()) {
-        case BluetoothA2dp.STATE_PLAYING:
-            if (mSuspending) {
-                mResuming = true;
-            }
-            return true;
-        case BluetoothA2dp.STATE_CONNECTED:
-            mResuming = resumeSinkNative(path);
-            mAudioManager.setParameters("A2dpSuspended=false");
-            return mResuming;
-        default:
-            return false;
-        }
+        mTargetA2dpState = BluetoothA2dp.STATE_PLAYING;
+        return checkSinkSuspendState(state.intValue());
     }
 
     public synchronized BluetoothDevice[] getConnectedSinks() {
@@ -458,10 +429,6 @@
     }
 
     private void handleSinkStateChange(BluetoothDevice device, int prevState, int state) {
-        if (state == BluetoothA2dp.STATE_DISCONNECTED) {
-            mSuspending = false;
-            mResuming = false;
-        }
         if (state != prevState) {
             if (state == BluetoothA2dp.STATE_DISCONNECTED ||
                     state == BluetoothA2dp.STATE_DISCONNECTING) {
@@ -477,28 +444,11 @@
             }
             mAudioDevices.put(device, state);
 
-            if (state == BluetoothA2dp.STATE_CONNECTED && prevState == BluetoothA2dp.STATE_PLAYING) {
-                if (DBG) log("handleSinkStateChange() STATE_PLAYING -> STATE_CONNECTED: mSuspending: "
-                        +mSuspending+", mResuming: "+mResuming);
-                if (mSuspending) {
-                    mSuspending = false;
-                    if (mResuming) {
-                        mResuming = false;
-                        resumeSink(device);
-                    }
-                }
-            }
-            if (state == BluetoothA2dp.STATE_PLAYING && prevState == BluetoothA2dp.STATE_CONNECTED) {
-                if (DBG) log("handleSinkStateChange() STATE_CONNECTED -> STATE_PLAYING: mSuspending: "
-                        +mSuspending+", mResuming: "+mResuming);
+            checkSinkSuspendState(state);
+            mTargetA2dpState = -1;
 
-                if (mResuming) {
-                    mResuming = false;
-                    if (mSuspending) {
-                        mSuspending = false;
-                        suspendSink(device);
-                    }
-                }
+            if (state == BluetoothA2dp.STATE_CONNECTING) {
+                mAudioManager.setParameters("A2dpSuspended=false");
             }
             Intent intent = new Intent(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
             intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
@@ -527,6 +477,23 @@
         return sinks;
     }
 
+    private boolean checkSinkSuspendState(int state) {
+        boolean result = true;
+
+        if (state != mTargetA2dpState) {
+            if (state == BluetoothA2dp.STATE_PLAYING &&
+                mTargetA2dpState == BluetoothA2dp.STATE_CONNECTED) {
+                mAudioManager.setParameters("A2dpSuspended=true");
+            } else if (state == BluetoothA2dp.STATE_CONNECTED &&
+                mTargetA2dpState == BluetoothA2dp.STATE_PLAYING) {
+                mAudioManager.setParameters("A2dpSuspended=false");
+            } else {
+                result = false;
+            }
+        }
+        return result;
+    }
+
     @Override
     protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mAudioDevices.isEmpty()) return;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index a92800d..afc6864 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -294,7 +294,12 @@
                                                      lbaseline, lbottom, buf,
                                                      start, end, par, this);
 
-                            left += margin.getLeadingMargin(par);
+                            boolean useMargin = par;
+                            if (margin instanceof LeadingMarginSpan.LeadingMarginSpan2) {
+                                int count = ((LeadingMarginSpan.LeadingMarginSpan2)margin).getLeadingMarginLineCount();
+                                useMargin = count > i;
+                            }
+                            left += margin.getLeadingMargin(useMargin);
                         }
                     }
                 }
@@ -1293,7 +1298,13 @@
                                                         LeadingMarginSpan.class);
 
                 for (int i = 0; i < spans.length; i++) {
-                    left += spans[i].getLeadingMargin(par);
+                    boolean margin = par;
+                    LeadingMarginSpan span = spans[i];
+                    if (span instanceof LeadingMarginSpan.LeadingMarginSpan2) {
+                        int count = ((LeadingMarginSpan.LeadingMarginSpan2)span).getLeadingMarginLineCount();
+                        margin = count >= line;
+                    }
+                    left += span.getLeadingMargin(margin);
                 }
             }
         }
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index f0a5ffd..fbf1261 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -161,6 +161,7 @@
             else
                 end++;
 
+            int firstWidthLineCount = 1;
             int firstwidth = outerwidth;
             int restwidth = outerwidth;
 
@@ -171,8 +172,12 @@
 
                 sp = spanned.getSpans(start, end, LeadingMarginSpan.class);
                 for (int i = 0; i < sp.length; i++) {
+                    LeadingMarginSpan lms = sp[i];
                     firstwidth -= sp[i].getLeadingMargin(true);
                     restwidth -= sp[i].getLeadingMargin(false);
+                    if (lms instanceof LeadingMarginSpan.LeadingMarginSpan2) {
+                        firstWidthLineCount = ((LeadingMarginSpan.LeadingMarginSpan2)lms).getLeadingMarginLineCount();
+                    }
                 }
 
                 chooseht = spanned.getSpans(start, end, LineHeightSpan.class);
@@ -750,7 +755,9 @@
                         fitascent = fitdescent = fittop = fitbottom = 0;
                         okascent = okdescent = oktop = okbottom = 0;
 
-                        width = restwidth;
+                        if (--firstWidthLineCount <= 0) {
+                            width = restwidth;
+                        }
                     }
                 }
             }
diff --git a/core/java/android/text/style/LeadingMarginSpan.java b/core/java/android/text/style/LeadingMarginSpan.java
index 8e212e3..cb55329 100644
--- a/core/java/android/text/style/LeadingMarginSpan.java
+++ b/core/java/android/text/style/LeadingMarginSpan.java
@@ -33,6 +33,11 @@
                                   CharSequence text, int start, int end,
                                   boolean first, Layout layout);
 
+
+    public interface LeadingMarginSpan2 extends LeadingMarginSpan, WrapTogetherSpan {
+        public int getLeadingMarginLineCount();
+    };
+
     public static class Standard implements LeadingMarginSpan, ParcelableSpan {
         private final int mFirst, mRest;
         
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index d2861cb..d1db35e 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -496,15 +496,18 @@
      * @param uri A String representing the URI of the desired file.
      * @param buffer The byte array to copy the data into.
      * @param offset The offet into buffer to place the data.
+     * @param expectSize The size that the buffer has allocated for this file.
      * @return int The size of the given file, or zero if it fails.
      */
-    private int getFile(String uri, byte[] buffer, int offset) {
+    private int getFile(String uri, byte[] buffer, int offset,
+            int expectedSize) {
         int size = 0;
         try {
             InputStream stream = mContext.getContentResolver()
                             .openInputStream(Uri.parse(uri));
             size = stream.available();
-            if (buffer != null && buffer.length - offset >= size) {
+            if (size <= expectedSize && buffer != null
+                    && buffer.length - offset >= size) {
                 stream.read(buffer, offset, size);
             } else {
                 size = 0;
diff --git a/core/java/android/webkit/ByteArrayBuilder.java b/core/java/android/webkit/ByteArrayBuilder.java
index 145411c..334526b 100644
--- a/core/java/android/webkit/ByteArrayBuilder.java
+++ b/core/java/android/webkit/ByteArrayBuilder.java
@@ -16,6 +16,8 @@
 
 package android.webkit;
 
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
 import java.util.LinkedList;
 import java.util.ListIterator;
 
@@ -23,47 +25,37 @@
     them back out.  It does not optimize for returning the result in a
     single array, though this is supported in the API. It is fastest
     if the retrieval can be done via iterating through chunks.
-
-    Things to add:
-      - consider dynamically increasing our min_capacity,
-        as we see mTotalSize increase
 */
 class ByteArrayBuilder {
 
     private static final int DEFAULT_CAPACITY = 8192;
 
+    // Global pool of chunks to be used by other ByteArrayBuilders.
+    private static final LinkedList<SoftReference<Chunk>> sPool =
+            new LinkedList<SoftReference<Chunk>>();
+    // Reference queue for processing gc'd entries.
+    private static final ReferenceQueue<Chunk> sQueue =
+            new ReferenceQueue<Chunk>();
+
     private LinkedList<Chunk> mChunks;
 
-    /** free pool */
-    private LinkedList<Chunk> mPool;
-
-    private int mMinCapacity;
-
     public ByteArrayBuilder() {
-        init(0);
-    }
-
-    public ByteArrayBuilder(int minCapacity) {
-        init(minCapacity);
-    }
-
-    private void init(int minCapacity) {
         mChunks = new LinkedList<Chunk>();
-        mPool = new LinkedList<Chunk>();
-
-        if (minCapacity <= 0) {
-            minCapacity = DEFAULT_CAPACITY;
-        }
-        mMinCapacity = minCapacity;
-    }
-
-    public void append(byte[] array) {
-        append(array, 0, array.length);
     }
 
     public synchronized void append(byte[] array, int offset, int length) {
         while (length > 0) {
-            Chunk c = appendChunk(length);
+            Chunk c = null;
+            if (mChunks.isEmpty()) {
+                c = obtainChunk(length);
+                mChunks.addLast(c);
+            } else {
+                c = mChunks.getLast();
+                if (c.mLength == c.mArray.length) {
+                    c = obtainChunk(length);
+                    mChunks.addLast(c);
+                }
+            }
             int amount = Math.min(length, c.mArray.length - c.mLength);
             System.arraycopy(array, offset, c.mArray, c.mLength, amount);
             c.mLength += amount;
@@ -75,7 +67,7 @@
     /**
      * The fastest way to retrieve the data is to iterate through the
      * chunks.  This returns the first chunk.  Note: this pulls the
-     * chunk out of the queue.  The caller must call releaseChunk() to
+     * chunk out of the queue.  The caller must call Chunk.release() to
      * dispose of it.
      */
     public synchronized Chunk getFirstChunk() {
@@ -83,23 +75,11 @@
         return mChunks.removeFirst();
     }
 
-    /**
-     * recycles chunk
-     */
-    public synchronized void releaseChunk(Chunk c) {
-        c.mLength = 0;
-        mPool.addLast(c);
-    }
-
-    public boolean isEmpty() {
+    public synchronized boolean isEmpty() {
         return mChunks.isEmpty();
     }
 
-    public int size() {
-        return mChunks.size();
-    }
-
-    public int getByteSize() {
+    public synchronized int getByteSize() {
         int total = 0;
         ListIterator<Chunk> it = mChunks.listIterator(0);
         while (it.hasNext()) {
@@ -112,37 +92,40 @@
     public synchronized void clear() {
         Chunk c = getFirstChunk();
         while (c != null) {
-            releaseChunk(c);
+            c.release();
             c = getFirstChunk();
         }
     }
 
-    private Chunk appendChunk(int length) {
-        if (length < mMinCapacity) {
-            length = mMinCapacity;
-        }
-
-        Chunk c;
-        if (mChunks.isEmpty()) {
-            c = obtainChunk(length);
-        } else {
-            c = mChunks.getLast();
-            if (c.mLength == c.mArray.length) {
-                c = obtainChunk(length);
+    // Must be called with lock held on sPool.
+    private void processPoolLocked() {
+        while (true) {
+            SoftReference<Chunk> entry = (SoftReference<Chunk>) sQueue.poll();
+            if (entry == null) {
+                break;
             }
+            sPool.remove(entry);
         }
-        return c;
     }
 
     private Chunk obtainChunk(int length) {
-        Chunk c;
-        if (mPool.isEmpty()) {
-            c = new Chunk(length);
-        } else {
-            c = mPool.removeFirst();
+        // Correct a small length.
+        if (length < DEFAULT_CAPACITY) {
+            length = DEFAULT_CAPACITY;
         }
-        mChunks.addLast(c);
-        return c;
+        synchronized (sPool) {
+            // Process any queued references and remove them from the pool.
+            processPoolLocked();
+            if (!sPool.isEmpty()) {
+                Chunk c = sPool.removeFirst().get();
+                // The first item may have been queued after processPoolLocked
+                // so check for null.
+                if (c != null) {
+                    return c;
+                }
+            }
+            return new Chunk(length);
+        }
     }
 
     public static class Chunk {
@@ -153,5 +136,19 @@
             mArray = new byte[length];
             mLength = 0;
         }
+
+        /**
+         * Release the chunk and make it available for reuse.
+         */
+        public void release() {
+            mLength = 0;
+            synchronized (sPool) {
+                // Add the chunk back to the pool as a SoftReference so it can
+                // be gc'd if needed.
+                sPool.offer(new SoftReference<Chunk>(this, sQueue));
+                sPool.notifyAll();
+            }
+        }
+
     }
 }
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index 17345bc..5c0ce3c 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -78,7 +78,7 @@
 
     private static int sNativeLoaderCount;
 
-    private final ByteArrayBuilder mDataBuilder = new ByteArrayBuilder(8192);
+    private final ByteArrayBuilder mDataBuilder = new ByteArrayBuilder();
 
     private String   mUrl;
     private WebAddress mUri;
@@ -522,17 +522,18 @@
      * IMPORTANT: as this is called from network thread, can't call native
      * directly
      * XXX: Unlike the other network thread methods, this method can do the
-     * work of decoding the data and appending it to the data builder because
-     * mDataBuilder is a thread-safe structure.
+     * work of decoding the data and appending it to the data builder.
      */
     public void data(byte[] data, int length) {
         if (DebugFlags.LOAD_LISTENER) {
             Log.v(LOGTAG, "LoadListener.data(): url: " + url());
         }
 
-        // Synchronize on mData because commitLoad may write mData to WebCore
-        // and we don't want to replace mData or mDataLength at the same time
-        // as a write.
+        // The reason isEmpty() and append() need to synchronized together is
+        // because it is possible for getFirstChunk() to be called multiple
+        // times between isEmpty() and append(). This could cause commitLoad()
+        // to finish before processing the newly appended data and no message
+        // will be sent.
         boolean sendMessage = false;
         synchronized (mDataBuilder) {
             sendMessage = mDataBuilder.isEmpty();
@@ -1009,28 +1010,34 @@
         if (mIsMainPageLoader) {
             String type = sCertificateTypeMap.get(mMimeType);
             if (type != null) {
-                // In the case of downloading certificate, we will save it to
-                // the KeyStore and stop the current loading so that it will not
-                // generate a new history page
-                byte[] cert = new byte[mDataBuilder.getByteSize()];
-                int offset = 0;
-                while (true) {
-                    ByteArrayBuilder.Chunk c = mDataBuilder.getFirstChunk();
-                    if (c == null) break;
+                // This must be synchronized so that no more data can be added
+                // after getByteSize returns.
+                synchronized (mDataBuilder) {
+                    // In the case of downloading certificate, we will save it
+                    // to the KeyStore and stop the current loading so that it
+                    // will not generate a new history page
+                    byte[] cert = new byte[mDataBuilder.getByteSize()];
+                    int offset = 0;
+                    while (true) {
+                        ByteArrayBuilder.Chunk c = mDataBuilder.getFirstChunk();
+                        if (c == null) break;
 
-                    if (c.mLength != 0) {
-                        System.arraycopy(c.mArray, 0, cert, offset, c.mLength);
-                        offset += c.mLength;
+                        if (c.mLength != 0) {
+                            System.arraycopy(c.mArray, 0, cert, offset, c.mLength);
+                            offset += c.mLength;
+                        }
+                        c.release();
                     }
-                    mDataBuilder.releaseChunk(c);
+                    CertTool.addCertificate(mContext, type, cert);
+                    mBrowserFrame.stopLoading();
+                    return;
                 }
-                CertTool.addCertificate(mContext, type, cert);
-                mBrowserFrame.stopLoading();
-                return;
             }
         }
 
-        // Give the data to WebKit now
+        // Give the data to WebKit now. We don't have to synchronize on
+        // mDataBuilder here because pulling each chunk removes it from the
+        // internal list so it cannot be modified.
         PerfChecker checker = new PerfChecker();
         ByteArrayBuilder.Chunk c;
         while (true) {
@@ -1047,7 +1054,7 @@
                 }
                 nativeAddData(c.mArray, c.mLength);
             }
-            mDataBuilder.releaseChunk(c);
+            c.release();
             checker.responseAlert("res nativeAddData");
         }
     }
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index fffba1b..84a8a3c 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -431,6 +431,8 @@
             sMimeTypeMap.loadEntry("text/calendar", "icz");
             sMimeTypeMap.loadEntry("text/comma-separated-values", "csv");
             sMimeTypeMap.loadEntry("text/css", "css");
+            sMimeTypeMap.loadEntry("text/html", "htm");
+            sMimeTypeMap.loadEntry("text/html", "html");
             sMimeTypeMap.loadEntry("text/h323", "323");
             sMimeTypeMap.loadEntry("text/iuls", "uls");
             sMimeTypeMap.loadEntry("text/mathml", "mml");
@@ -481,6 +483,7 @@
             sMimeTypeMap.loadEntry("video/dv", "dif");
             sMimeTypeMap.loadEntry("video/dv", "dv");
             sMimeTypeMap.loadEntry("video/fli", "fli");
+            sMimeTypeMap.loadEntry("video/m4v", "m4v");
             sMimeTypeMap.loadEntry("video/mpeg", "mpeg");
             sMimeTypeMap.loadEntry("video/mpeg", "mpg");
             sMimeTypeMap.loadEntry("video/mpeg", "mpe");
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
index 232ed36..211e5e4 100644
--- a/core/java/android/webkit/URLUtil.java
+++ b/core/java/android/webkit/URLUtil.java
@@ -367,19 +367,23 @@
 
     /** Regex used to parse content-disposition headers */
     private static final Pattern CONTENT_DISPOSITION_PATTERN =
-            Pattern.compile("attachment;\\s*filename\\s*=\\s*\"([^\"]*)\"");
+            Pattern.compile("attachment;\\s*filename\\s*=\\s*(\"?)([^\"]*)\\1\\s*$",
+            Pattern.CASE_INSENSITIVE);
 
     /*
      * Parse the Content-Disposition HTTP Header. The format of the header
      * is defined here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html
      * This header provides a filename for content that is going to be
      * downloaded to the file system. We only support the attachment type.
+     * Note that RFC 2616 specifies the filename value must be double-quoted.
+     * Unfortunately some servers do not quote the value so to maintain
+     * consistent behaviour with other browsers, we allow unquoted values too.
      */
     static String parseContentDisposition(String contentDisposition) {
         try {
             Matcher m = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition);
             if (m.find()) {
-                return m.group(1);
+                return m.group(2);
             }
         } catch (IllegalStateException ex) {
              // This function is defined as returning null when it can't parse the header
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 3dd3b37..06ab14d 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -390,6 +390,8 @@
     private static final int LONG_PRESS_TIMEOUT = 1000;
     // needed to avoid flinging after a pause of no movement
     private static final int MIN_FLING_TIME = 250;
+    // draw unfiltered after drag is held without movement
+    private static final int MOTIONLESS_TIME = 100;
     // The time that the Zoom Controls are visible before fading away
     private static final long ZOOM_CONTROLS_TIMEOUT =
             ViewConfiguration.getZoomControlsTimeout();
@@ -427,6 +429,10 @@
     private Scroller mScroller;
 
     private boolean mWrapContent;
+    private static final int MOTIONLESS_FALSE           = 0;
+    private static final int MOTIONLESS_PENDING         = 1;
+    private static final int MOTIONLESS_TRUE            = 2;
+    private int mHeldMotionless;
 
     /**
      * Private message ids
@@ -438,6 +444,8 @@
     private static final int RELEASE_SINGLE_TAP         = 5;
     private static final int REQUEST_FORM_DATA          = 6;
     private static final int RESUME_WEBCORE_UPDATE      = 7;
+    private static final int DRAG_HELD_MOTIONLESS       = 8;
+    private static final int AWAKEN_SCROLL_BARS         = 9;
 
     //! arg1=x, arg2=y
     static final int SCROLL_TO_MSG_ID                   = 10;
@@ -468,9 +476,9 @@
         "SWITCH_TO_LONGPRESS", //            = 4;
         "RELEASE_SINGLE_TAP", //             = 5;
         "REQUEST_FORM_DATA", //              = 6;
-        "SWITCH_TO_CLICK", //                = 7;
-        "RESUME_WEBCORE_UPDATE", //          = 8;
-        "9",
+        "RESUME_WEBCORE_UPDATE", //          = 7;
+        "DRAG_HELD_MOTIONLESS", //           = 8;
+        "AWAKEN_SCROLL_BARS", //             = 9;
         "SCROLL_TO_MSG_ID", //               = 10;
         "SCROLL_BY_MSG_ID", //               = 11;
         "SPAWN_SCROLL_TO_MSG_ID", //         = 12;
@@ -1713,6 +1721,7 @@
      *            as the data member with "url" as key. The result can be null.
      */
     public void requestImageRef(Message msg) {
+        if (0 == mNativeClass) return; // client isn't initialized
         int contentX = viewToContentX((int) mLastTouchX + mScrollX);
         int contentY = viewToContentY((int) mLastTouchY + mScrollY);
         String ref = nativeImageURI(contentX, contentY);
@@ -2331,6 +2340,7 @@
      * @param forward Direction to search.
      */
     public void findNext(boolean forward) {
+        if (0 == mNativeClass) return; // client isn't initialized
         nativeFindNext(forward);
     }
 
@@ -2341,6 +2351,7 @@
      *              that were found.
      */
     public int findAll(String find) {
+        if (0 == mNativeClass) return 0; // client isn't initialized
         if (mFindIsUp == false) {
             recordNewContentSize(mContentWidth, mContentHeight + mFindHeight,
                     false);
@@ -2870,8 +2881,22 @@
         }
 
         boolean animateZoom = mZoomScale != 0;
-        boolean animateScroll = !mScroller.isFinished()
-                || mVelocityTracker != null;
+        boolean animateScroll = (!mScroller.isFinished()
+                || mVelocityTracker != null)
+                && (mTouchMode != TOUCH_DRAG_MODE ||
+                mHeldMotionless != MOTIONLESS_TRUE);
+        if (mTouchMode == TOUCH_DRAG_MODE) {
+            if (mHeldMotionless == MOTIONLESS_PENDING) {
+                mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
+                mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
+                mHeldMotionless = MOTIONLESS_FALSE;
+            }
+            if (mHeldMotionless == MOTIONLESS_FALSE) {
+                mPrivateHandler.sendMessageDelayed(mPrivateHandler
+                        .obtainMessage(DRAG_HELD_MOTIONLESS), MOTIONLESS_TIME);
+                mHeldMotionless = MOTIONLESS_PENDING;
+            }
+        }
         if (animateZoom) {
             float zoomScale;
             int interval = (int) (SystemClock.uptimeMillis() - mZoomStart);
@@ -2945,12 +2970,12 @@
                 animateScroll);
 
         if (mNativeClass == 0) return;
-        if (mShiftIsPressed) {
+        if (mShiftIsPressed && !animateZoom) {
             if (mTouchSelection) {
                 nativeDrawSelectionRegion(canvas);
             } else {
-                nativeDrawSelection(canvas, mSelectX, mSelectY,
-                        mExtendSelection);
+                nativeDrawSelection(canvas, mInvActualScale, getTitleHeight(),
+                        mSelectX, mSelectY, mExtendSelection);
             }
         } else if (drawCursorRing) {
             if (mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
@@ -3455,6 +3480,7 @@
      * @hide
      */
     public void emulateShiftHeld() {
+        if (0 == mNativeClass) return; // client isn't initialized
         mExtendSelection = false;
         mShiftIsPressed = true;
         nativeHideCursor();
@@ -3726,8 +3752,10 @@
             mLastSentTouchTime = eventTime;
         }
 
-        int deltaX = (int) (mLastTouchX - x);
-        int deltaY = (int) (mLastTouchY - y);
+        float fDeltaX = mLastTouchX - x;
+        float fDeltaY = mLastTouchY - y;
+        int deltaX = (int) fDeltaX;
+        int deltaY = (int) fDeltaY;
 
         switch (action) {
             case MotionEvent.ACTION_DOWN: {
@@ -3853,13 +3881,27 @@
 
                 // do pan
                 int newScrollX = pinLocX(mScrollX + deltaX);
-                deltaX = newScrollX - mScrollX;
+                int newDeltaX = newScrollX - mScrollX;
+                if (deltaX != newDeltaX) {
+                    deltaX = newDeltaX;
+                    fDeltaX = (float) newDeltaX;
+                }
                 int newScrollY = pinLocY(mScrollY + deltaY);
-                deltaY = newScrollY - mScrollY;
+                int newDeltaY = newScrollY - mScrollY;
+                if (deltaY != newDeltaY) {
+                    deltaY = newDeltaY;
+                    fDeltaY = (float) newDeltaY;
+                }
                 boolean done = false;
-                if (deltaX == 0 && deltaY == 0) {
-                    done = true;
+                boolean keepScrollBarsVisible = false;
+                if (Math.abs(fDeltaX) < 1.0f && Math.abs(fDeltaY) < 1.0f) {
+                    keepScrollBarsVisible = done = true;
                 } else {
+                    if (mHeldMotionless != MOTIONLESS_FALSE) {
+                        mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
+                        mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
+                        mHeldMotionless = MOTIONLESS_FALSE;
+                    }
                     if (mSnapScrollMode == SNAP_X || mSnapScrollMode == SNAP_Y) {
                         int ax = Math.abs(deltaX);
                         int ay = Math.abs(deltaY);
@@ -3899,8 +3941,7 @@
                         if (deltaX == 0) {
                             // keep the scrollbar on the screen even there is no
                             // scroll
-                            awakenScrollBars(ViewConfiguration
-                                    .getScrollDefaultDelay(), false);
+                            keepScrollBarsVisible = true;
                         } else {
                             scrollBy(deltaX, 0);
                         }
@@ -3910,8 +3951,7 @@
                         if (deltaY == 0) {
                             // keep the scrollbar on the screen even there is no
                             // scroll
-                            awakenScrollBars(ViewConfiguration
-                                    .getScrollDefaultDelay(), false);
+                            keepScrollBarsVisible = true;
                         } else {
                             scrollBy(0, deltaY);
                         }
@@ -3938,13 +3978,17 @@
                     }
                 }
 
-                if (done) {
+                if (keepScrollBarsVisible) {
+                    if (mHeldMotionless != MOTIONLESS_TRUE) {
+                        mHeldMotionless = MOTIONLESS_TRUE;
+                        invalidate();
+                    }
                     // keep the scrollbar on the screen even there is no scroll
                     awakenScrollBars(ViewConfiguration.getScrollDefaultDelay(),
                             false);
                     // return false to indicate that we can't pan out of the
                     // view space
-                    return false;
+                    return !done;
                 }
                 break;
             }
@@ -3997,6 +4041,9 @@
                             break;
                         }
                     case TOUCH_DRAG_MODE:
+                        mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
+                        mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
+                        mHeldMotionless = MOTIONLESS_TRUE;
                         // redraw in high-quality, as we're done dragging
                         invalidate();
                         // if the user waits a while w/o moving before the
@@ -4036,6 +4083,9 @@
                 }
                 mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
                 mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+                mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
+                mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
+                mHeldMotionless = MOTIONLESS_TRUE;
                 mTouchMode = TOUCH_DONE_MODE;
                 nativeHideCursor();
                 break;
@@ -4091,6 +4141,9 @@
             return true;
         }
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (mShiftIsPressed) {
+                return true; // discard press if copy in progress
+            }
             mTrackballDown = true;
             if (mNativeClass == 0) {
                 return false;
@@ -4119,6 +4172,7 @@
                 } else {
                     mExtendSelection = true;
                 }
+                return true; // discard press if copy in progress
             }
             if (DebugFlags.WEB_VIEW) {
                 Log.v(LOGTAG, "onTrackballEvent up ev=" + ev
@@ -4618,9 +4672,6 @@
         }
         int x = viewToContentX((int) event.getX() + mWebTextView.getLeft());
         int y = viewToContentY((int) event.getY() + mWebTextView.getTop());
-        // In case the soft keyboard has been dismissed, bring it back up.
-        InputMethodManager.getInstance(getContext()).showSoftInput(mWebTextView,
-                0);
         if (nativeFocusNodePointer() != nativeCursorNodePointer()) {
             nativeMotionUp(x, y, mNavSlop);
         }
@@ -5203,6 +5254,21 @@
                     }
                     break;
 
+                case DRAG_HELD_MOTIONLESS:
+                    mHeldMotionless = MOTIONLESS_TRUE;
+                    invalidate();
+                    // fall through to keep scrollbars awake
+
+                case AWAKEN_SCROLL_BARS:
+                    if (mTouchMode == TOUCH_DRAG_MODE
+                            && mHeldMotionless == MOTIONLESS_TRUE) {
+                        awakenScrollBars(ViewConfiguration
+                                .getScrollDefaultDelay(), false);
+                        mPrivateHandler.sendMessageDelayed(mPrivateHandler
+                                .obtainMessage(AWAKEN_SCROLL_BARS),
+                                ViewConfiguration.getScrollDefaultDelay());
+                    }
+                    break;
                 default:
                     super.handleMessage(msg);
                     break;
@@ -5609,6 +5675,17 @@
     }
 
     /**
+     * Draw the HTML page into the specified canvas. This call ignores any
+     * view-specific zoom, scroll offset, or other changes. It does not draw
+     * any view-specific chrome, such as progress or URL bars.
+     *
+     * @hide only needs to be accessible to Browser and testing
+     */
+    public void drawPage(Canvas canvas) {
+        mWebViewCore.drawContentPicture(canvas, 0, false, false);
+    }
+
+    /**
      *  Update our cache with updatedText.
      *  @param updatedText  The new text to put in our cache.
      */
@@ -5638,8 +5715,8 @@
     private native void     nativeDestroy();
     private native void     nativeDrawCursorRing(Canvas content);
     private native void     nativeDrawMatches(Canvas canvas);
-    private native void     nativeDrawSelection(Canvas content
-            , int x, int y, boolean extendSelection);
+    private native void     nativeDrawSelection(Canvas content, float scale,
+            int offset, int x, int y, boolean extendSelection);
     private native void     nativeDrawSelectionRegion(Canvas content);
     private native void     nativeDumpDisplayTree(String urlOrNull);
     private native int      nativeFindAll(String findLower, String findUpper);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 4bac593..d5ccdeb 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -37,7 +37,7 @@
     void notePhoneOff();
     void notePhoneSignalStrength(in SignalStrength signalStrength);
     void notePhoneDataConnectionState(int dataType, boolean hasData);
-    void noteAirplaneMode(boolean isAirplaneMode);
+    void notePhoneState(int phoneState);
     void noteWifiOn(int uid);
     void noteWifiOff(int uid);
     void noteWifiRunning();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 4b26b8f..8698cb7 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -24,6 +24,7 @@
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.SystemClock;
+import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.util.Log;
@@ -56,7 +57,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS' 
 
     // Current on-disk Parcel version
-    private static final int VERSION = 40;
+    private static final int VERSION = 41;
 
     private static int sNumSpeedSteps;
 
@@ -117,7 +118,9 @@
     int mPhoneSignalStrengthBin = -1;
     final StopwatchTimer[] mPhoneSignalStrengthsTimer = 
             new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS];
-    
+
+    StopwatchTimer mPhoneSignalScanningTimer;
+
     int mPhoneDataConnectionType = -1;
     final StopwatchTimer[] mPhoneDataConnectionsTimer = 
             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
@@ -169,6 +172,8 @@
     private int mBluetoothPingCount;
     private int mBluetoothPingStart = -1;
 
+    private int mPhoneServiceState = -1;
+
     /*
      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
      */
@@ -681,6 +686,8 @@
          */
         long mAcquireTime;
 
+        long mTimeout;
+
         StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
                 ArrayList<Unpluggable> unpluggables, Parcel in) {
             super(type, unpluggables, in);
@@ -694,6 +701,10 @@
             mTimerPool = timerPool;
         }
         
+        void setTimeout(long timeout) {
+            mTimeout = timeout;
+        }
+
         public void writeToParcel(Parcel out, long batteryRealtime) {
             super.writeToParcel(out, batteryRealtime);
             out.writeLong(mUpdateTime);
@@ -797,6 +808,9 @@
 
         @Override
         protected long computeRunTimeLocked(long curBatteryRealtime) {
+            if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
+                curBatteryRealtime = mUpdateTime + mTimeout;
+            }
             return mTotalTime + (mNesting > 0
                     ? (curBatteryRealtime - mUpdateTime)
                             / (mTimerPool != null ? mTimerPool.size() : 1)
@@ -1123,34 +1137,59 @@
         }
     }
 
-    public void noteAirplaneModeLocked(boolean isAirplaneMode) {
-        final int bin = mPhoneSignalStrengthBin;
-        if (bin >= 0) {
-            if (!isAirplaneMode) {
-                if (!mPhoneSignalStrengthsTimer[bin].isRunningLocked()) {
-                    mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
-                }
-            } else {
-                for (int i = 0; i < NUM_SIGNAL_STRENGTH_BINS; i++) {
-                    while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
-                        mPhoneSignalStrengthsTimer[i].stopRunningLocked(this);
-                    }
+    /**
+     * Telephony stack updates the phone state.
+     * @param state phone state from ServiceState.getState()
+     */
+    public void notePhoneStateLocked(int state) {
+        int bin = mPhoneSignalStrengthBin;
+        boolean isAirplaneMode = state == ServiceState.STATE_POWER_OFF;
+        // Stop all timers
+        if (isAirplaneMode || state == ServiceState.STATE_OUT_OF_SERVICE) {
+            for (int i = 0; i < NUM_SIGNAL_STRENGTH_BINS; i++) {
+                while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
+                    mPhoneSignalStrengthsTimer[i].stopRunningLocked(this);
                 }
             }
         }
+        // Stop Signal Scanning timer, in case we're going into service
+        while (mPhoneSignalScanningTimer.isRunningLocked()) {
+            mPhoneSignalScanningTimer.stopRunningLocked(this);
+        }
+
+        // If we're back in service or continuing in service, restart the old timer.
+        if (state == ServiceState.STATE_IN_SERVICE) {
+            if (bin == -1) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            if (!mPhoneSignalStrengthsTimer[bin].isRunningLocked()) {
+                mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
+            }
+        } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
+            mPhoneSignalStrengthBin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            if (!mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].isRunningLocked()) {
+                mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].startRunningLocked(this);
+            }
+            if (!mPhoneSignalScanningTimer.isRunningLocked()) {
+                mPhoneSignalScanningTimer.startRunningLocked(this);
+            }
+        }
+        mPhoneServiceState = state;
     }
 
     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
         // Bin the strength.
         int bin;
-
+        if (mPhoneServiceState == ServiceState.STATE_POWER_OFF
+                || mPhoneServiceState == ServiceState.STATE_OUT_OF_SERVICE) {
+            // Ignore any signal strength changes when radio was turned off or out of service.
+            return;
+        }
         if (!signalStrength.isGsm()) {
             int dBm = signalStrength.getCdmaDbm();
-            if (dBm >= -75) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-            else if (dBm >= -85) bin = SIGNAL_STRENGTH_GREAT;
-            else if (dBm >= -95)  bin = SIGNAL_STRENGTH_GOOD;
-            else if (dBm >= -100)  bin = SIGNAL_STRENGTH_MODERATE;
-            else bin = SIGNAL_STRENGTH_POOR;
+            if (dBm >= -75) bin = SIGNAL_STRENGTH_GREAT;
+            else if (dBm >= -85) bin = SIGNAL_STRENGTH_GOOD;
+            else if (dBm >= -95)  bin = SIGNAL_STRENGTH_MODERATE;
+            else if (dBm >= -100)  bin = SIGNAL_STRENGTH_POOR;
+            else bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
         } else {
             int asu = signalStrength.getGsmSignalStrength();
             if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
@@ -1328,7 +1367,13 @@
         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
                 batteryRealtime, which);
     }
-    
+
+    @Override public long getPhoneSignalScanningTime(
+            long batteryRealtime, int which) {
+        return mPhoneSignalScanningTimer.getTotalTimeLocked(
+                batteryRealtime, which);
+    }
+
     @Override public int getPhoneSignalStrengthCount(int dataType, int which) {
         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
     }
@@ -2653,6 +2698,7 @@
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables);
         }
+        mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables);
         }
@@ -2679,6 +2725,12 @@
         if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
     }
 
+    public void setRadioScanningTimeout(long timeout) {
+        if (mPhoneSignalScanningTimer != null) {
+            mPhoneSignalScanningTimer.setTimeout(timeout);
+        }
+    }
+
     @Override
     public int getStartCount() {
         return mStartCount;
@@ -3114,6 +3166,7 @@
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
         }
+        mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
         }
@@ -3257,6 +3310,7 @@
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
         }
+        mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
         }
@@ -3418,6 +3472,7 @@
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in);
         }
+        mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables, in);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in);
         }
@@ -3513,6 +3568,7 @@
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime);
         }
+        mPhoneSignalScanningTimer.writeToParcel(out, batteryRealtime);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
             mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime);
         }
@@ -3598,6 +3654,8 @@
                 pr.println("*** Signal strength #" + i + ":");
                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
             }
+            pr.println("*** Signal scanning :");
+            mPhoneSignalScanningTimer.logState(pr, "  ");
             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
                 pr.println("*** Data connection type #" + i + ":");
                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 4b4b717..2369d25 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -97,6 +97,11 @@
     public static final String POWER_RADIO_ON = "radio.on";
 
     /**
+     * Power consumption when cell radio is hunting for a signal.
+     */
+    public static final String POWER_RADIO_SCANNING = "radio.scanning";
+
+    /**
      * Power consumption when talking on the phone.
      */
     public static final String POWER_RADIO_ACTIVE = "radio.active";
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 62a50e5..d2e9454 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -735,7 +735,6 @@
         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     }
 
-    // STOPSHIP: Change to LOGV
     LOGE("%s: Received signal %s:%s from %s", __FUNCTION__,
         dbus_message_get_interface(msg), dbus_message_get_member(msg),
         dbus_message_get_path(msg));
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png b/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
index 30a68d0..338d840 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png b/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png
index 548d0bd..bf45e38 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png
Binary files differ
diff --git a/core/res/res/layout/alert_dialog.xml b/core/res/res/layout/alert_dialog.xml
index cf2de05..40e3f42 100644
--- a/core/res/res/layout/alert_dialog.xml
+++ b/core/res/res/layout/alert_dialog.xml
@@ -50,11 +50,11 @@
                 android:paddingTop="6dip"
                 android:paddingRight="10dip"
                 android:src="@drawable/ic_dialog_info" />
-            <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle" 
+            <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
                 style="?android:attr/textAppearanceLarge"
                 android:singleLine="true"
                 android:ellipsize="end"
-                android:layout_width="fill_parent" 
+                android:layout_width="fill_parent"
                 android:layout_height="wrap_content" />
         </LinearLayout>
         <ImageView android:id="@+id/titleDivider"
@@ -63,9 +63,7 @@
             android:visibility="gone"
             android:scaleType="fitXY"
             android:gravity="fill_horizontal"
-            android:src="@android:drawable/dialog_divider_horizontal_light"
-            android:layout_marginLeft="10dip"
-            android:layout_marginRight="10dip"/>
+            android:src="@android:drawable/divider_horizontal_dark" />
         <!-- If the client uses a customTitle, it will be added here. -->
     </LinearLayout>
 
@@ -88,7 +86,7 @@
                 android:padding="5dip" />
         </ScrollView>
     </LinearLayout>
-        
+
     <FrameLayout android:id="@+id/customPanel"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
@@ -99,13 +97,13 @@
             android:paddingTop="5dip"
             android:paddingBottom="5dip" />
     </FrameLayout>
-        
+
     <LinearLayout android:id="@+id/buttonPanel"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:minHeight="54dip"
-        android:orientation="vertical" >     
-        <LinearLayout 
+        android:orientation="vertical" >
+        <LinearLayout
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
diff --git a/core/res/res/layout/grant_credentials_permission.xml b/core/res/res/layout/grant_credentials_permission.xml
index fe1c22e..84b66230 100644
--- a/core/res/res/layout/grant_credentials_permission.xml
+++ b/core/res/res/layout/grant_credentials_permission.xml
@@ -1,41 +1,163 @@
 <?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.
-*/
+/**
+ * Copyright (c) 2008, Google Inc.
+ *
+ * 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"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
     android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
+    android:layout_height="fill_parent">
+
+    <!-- The header -->
     <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/message" />
-    <Button android:id="@+id/allow"
+        android:id="@+id/header_text"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:text="@string/allow" />
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textColor="@color/white"
+        android:textStyle="bold"
+        android:text="@string/grant_permissions_header_text"
+        android:shadowColor="@color/shadow"
+        android:shadowRadius="2"
+        android:singleLine="true"
+        android:background="@drawable/title_bar_medium"
+        android:gravity="left|center_vertical"
+	android:paddingLeft="19dip"
+        android:ellipsize="marquee" />
 
-    <Button android:id="@+id/deny"
+    <!-- The list of packages that correspond to the requesting UID
+    and the account/authtokenType that is being requested -->
+    <ScrollView
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:text="@string/deny" />
+        android:fillViewport="true"
+        android:layout_weight="1"
+        android:gravity="top|center_horizontal"
+        android:foreground="@drawable/title_bar_shadow">
 
-    <ListView android:id="@+id/packages_list"
-       android:layout_width="fill_parent" android:layout_height="fill_parent"/>
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:paddingTop="14dip"
+            android:orientation="vertical">
 
+            <TextView
+                android:id="@+id/grant_credentials_permission_message_header"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/grant_credentials_permission_message_header"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:paddingLeft="19dip"
+                android:paddingBottom="12dip" />
+
+            <LinearLayout
+                android:id="@+id/packages_list"
+                android:orientation="vertical"
+                android:paddingLeft="16dip"
+                android:paddingRight="12dip"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content" />
+
+            <RelativeLayout
+                android:paddingLeft="16dip"
+                android:paddingRight="12dip"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+
+                <ImageView
+                    android:id="@+id/permission_icon"
+                    android:layout_width="30dip"
+                    android:layout_height="30dip"
+                    android:src="@drawable/ic_bullet_key_permission"
+                    android:layout_alignParentLeft="true"
+                    android:scaleType="fitCenter" />
+
+                <TextView
+                    android:id="@+id/account_type"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:textColor="@color/perms_dangerous_perm_color"
+                    android:textStyle="bold"
+                    android:paddingLeft="6dip"
+                    android:layout_toRightOf="@id/permission_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/account_name"
+                    android:textAppearance="?android:attr/textAppearanceSmall"
+                    android:textColor="@color/perms_dangerous_perm_color"
+                    android:layout_marginTop="-4dip"
+                    android:paddingBottom="8dip"
+                    android:paddingLeft="6dip"
+                    android:layout_below="@id/account_type"
+                    android:layout_toRightOf="@id/permission_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/authtoken_type"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:textColor="@color/perms_dangerous_perm_color"
+                    android:textStyle="bold"
+                    android:layout_marginTop="-4dip"
+                    android:paddingBottom="8dip"
+                    android:paddingLeft="6dip"
+                    android:layout_below="@id/account_name"
+                    android:layout_toRightOf="@id/permission_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+            </RelativeLayout>
+
+            <TextView
+                android:id="@+id/grant_credentials_permission_message_footer"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/grant_credentials_permission_message_footer"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:paddingLeft="19dip"
+                android:paddingBottom="12dip" />
+        </LinearLayout>
+    </ScrollView>
+
+    <!-- The buttons to allow or deny -->
+    <LinearLayout
+        android:id="@+id/buttons"
+        android:layout_width="fill_parent"
+        android:layout_height="52dip"
+        android:background="@drawable/bottom_bar"
+        android:paddingTop="4dip"
+        android:paddingLeft="2dip"
+        android:paddingRight="2dip">
+
+        <Button
+            android:id="@+id/allow_button"
+            android:text="@string/allow"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="2" />
+
+        <Button
+            android:id="@+id/deny_button"
+            android:text="@string/deny"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="2" />
+
+    </LinearLayout>
 </LinearLayout>
+
diff --git a/core/res/res/layout/permissions_account_and_authtokentype.xml b/core/res/res/layout/permissions_account_and_authtokentype.xml
new file mode 100644
index 0000000..4494a2c5
--- /dev/null
+++ b/core/res/res/layout/permissions_account_and_authtokentype.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!--
+  Defines the layout of an account and authtoken type permission item.
+  Contains an icon, the account type and name and the authtoken type.
+-->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <ImageView
+        android:id="@+id/permission_icon"
+        android:layout_width="30dip"
+        android:layout_height="30dip"
+        android:drawable="@drawable/ic_bullet_key_permission"
+        android:layout_alignParentLeft="true"
+        android:scaleType="fitCenter" />
+
+
+    <TextView
+        android:id="@+id/account_type"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textStyle="bold"
+        android:paddingLeft="6dip"
+        android:layout_toRightOf="@id/permission_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:id="@+id/account_name"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:layout_marginTop="-4dip"
+        android:paddingBottom="8dip"
+        android:paddingLeft="6dip"
+        android:layout_below="@id/account_type"
+        android:layout_toRightOf="@id/permission_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:id="@+id/authtoken_type"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:layout_marginTop="-4dip"
+        android:paddingBottom="8dip"
+        android:paddingLeft="6dip"
+        android:layout_below="@id/account_name"
+        android:layout_toRightOf="@id/permission_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</RelativeLayout>
diff --git a/core/res/res/layout/permissions_package_list_item.xml b/core/res/res/layout/permissions_package_list_item.xml
new file mode 100644
index 0000000..1bffe51
--- /dev/null
+++ b/core/res/res/layout/permissions_package_list_item.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!--
+  Defines the layout of a single package item.
+  Contains a bullet point icon and the name of the package.
+-->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <ImageView
+        android:id="@+id/package_icon"
+        android:layout_width="30dip"
+        android:layout_height="30dip"
+        android:layout_alignParentLeft="true"
+        android:src="@drawable/ic_text_dot"
+        android:scaleType="fitCenter" />
+
+
+    <TextView
+        android:id="@+id/package_label"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textStyle="bold"
+        android:paddingLeft="6dip"
+        android:layout_toRightOf="@id/package_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</RelativeLayout>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index fba6c08..67fac9f 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Sleduje vaši fyzickou polohu"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Síťová komunikace"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Umožňuje aplikacím získat přístup k různým funkcím sítě."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Vaše účty Google"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Přístup k dostupným účtům Google."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Řízení hardwaru"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Přímý přístup k hardwaru telefonu."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Telefonní hovory"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Zadejte kód PIN"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Nesprávný kód PIN"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Chcete-li telefon odemknout, stiskněte Menu a poté 0."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Zkuste to prosím znovu"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Nabíjení (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Nabito."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Připojte dobíjecí zařízení."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Není vložena SIM karta."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"V telefonu není žádná karta SIM."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Nabíjení..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Prosím připojte dobíjecí zařízení"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Baterie je vybitá:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"zbývá méně než <xliff:g id="NUMBER">%d%%</xliff:g>."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Využití baterie"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Test továrního nastavení se nezdařil"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Test FACTORY_TEST lze provést pouze u balíčků nainstalovaných ve složce /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Chcete opustit tuto stránku?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Vyberte OK, chcete-li pokračovat, nebo Zrušit, chcete-li na stránce zůstat."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Potvrdit"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"čtení historie a záložek Prohlížeče"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umožňuje aplikaci číst všechny navštívené adresy URL a záložky Prohlížeče."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"zápis do historie a záložek Prohlížeče"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Vytvořit kontakt"\n"pro <xliff:g id="NUMBER">%s</xliff:g>."</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"Zaškrtnuto"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"Nezaškrtnuto"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Uvedené aplikace od <xliff:g id="APPLICATION">%2$s</xliff:g> požadují oprávnění přistupovat k přihlašovacím údajům účtu <xliff:g id="ACCOUNT">%1$s</xliff:g>. Chcete toto oprávnění udělit? Pokud je udělíte, vaše odpověď se uloží a tato výzva se již nebude zobrazovat."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Uvedené aplikace požadují od <xliff:g id="APPLICATION">%3$s</xliff:g> oprávnění přistupovat k přihlašovacím údajům (typ: <xliff:g id="TYPE">%1$s</xliff:g>) účtu <xliff:g id="ACCOUNT">%2$s</xliff:g>. Chcete toto oprávnění udělit? Pokud je udělíte, vaše odpověď se uloží a tato výzva se již nebude zobrazovat."</string>
     <string name="allow" msgid="7225948811296386551">"Povolit"</string>
     <string name="deny" msgid="2081879885755434506">"Odepřít"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Požadováno oprávnění"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Usnadnění"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Změnit tapetu"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 99f8ec9..7b37709 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Overvåg din fysiske placering"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Netværkskommunikation"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Tillader programmer at få adgang til forskellige netværksfunktioner."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Dine Google-konti"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Få adgang til tilgængelige Google-konti."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardwarekontroller"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Direkte adgang til hardware på håndsættet."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Telefonopkald"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Indtast PIN-kode"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Forkert PIN-kode!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Tryk på Menu og dernæst på 0 for at låse op."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Beklager! Prøv igen"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Oplader (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Opladt."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Tilslut din oplader."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Der er ikke noget SIM-kort."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Der er ikke noget SIM-kort i telefonen."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Oplader ..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Forbind oplader"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteriet er ved at blive tomt:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"mindre end <xliff:g id="NUMBER">%d%%</xliff:g> tilbage."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Batteriforbrug"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Fabrikstest mislykkedes"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Handlingen FACTORY_TEST understøttes kun af pakker installeret i /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"Javascript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Naviger væk fra denne side?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n" Vælg OK for at fortsætte eller Annuller for at blive på den aktuelle side."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Bekræft"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"læs browserens oversigt og bogmærker"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillader programmet at læse alle de webadresser, browseren har besøgt, og alle browserens bogmærker."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriv browserens oversigt og bogmærker"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Opret kontakt"\n"ved hjælp af <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"kontrolleret"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"ikke kontrolleret"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"De nævnte programmer beder om tilladelse til at få adgang til loginoplysningerne til kontoen <xliff:g id="ACCOUNT">%1$s</xliff:g> fra <xliff:g id="APPLICATION">%2$s</xliff:g>. Ønsker du at give denne tilladelse? Hvis ja, så huskes dit svar, og du vil ikke blive spurgt om det igen."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"De nævnte programmer beder om tilladelse til at få adgang til <xliff:g id="TYPE">%1$s</xliff:g>-loginoplysningerne til kontoen <xliff:g id="ACCOUNT">%2$s</xliff:g> fra <xliff:g id="APPLICATION">%3$s</xliff:g>. Vil du give denne tilladelse? Hvis ja, så huskes dit svar, og du vil ikke blive spurgt om det igen."</string>
     <string name="allow" msgid="7225948811296386551">"Tillad"</string>
     <string name="deny" msgid="2081879885755434506">"Afvis"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Der er anmodet om tilladelse"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Tilgængelighed"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapet"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Skift tapet"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 02f685a..af68303c 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Ihren physischen Standort überwachen"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Netzwerkkommunikation"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Ermöglicht Anwendungen den Zugriff auf verschiedene Netzwerkfunktionen."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Ihre Google-Konten"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Greift auf verfügbare Google-Konten zu."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardware-Steuerelemente"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Direkter Zugriff auf Hardware über Headset"</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Anrufe"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN-Code eingeben"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Falscher PIN-Code!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Drücken Sie zum Entsperren die Menütaste und dann auf \"0\"."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Tut uns leid. Versuchen Sie es noch einmal."</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Wird geladen (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Aufgeladen"</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Bitte Ladegerät anschließen"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Keine SIM-Karte."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Keine SIM-Karte im Telefon."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Wird aufgeladen..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Ladegerät anschließen"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Akku ist fast leer."</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"Nur noch weniger als <xliff:g id="NUMBER">%d%%</xliff:g> vorhanden."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Akkuverbrauch"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Werkstest fehlgeschlagen"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Die Aktion FACTORY_TEST wird nur für unter \"/system/app\" gespeicherte Pakete unterstützt."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Von dieser Seite navigieren?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Wählen Sie \"OK\", um fortzufahren, oder wählen Sie \"Abbrechen\", um auf der aktuellen Seite zu bleiben."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Bestätigen"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Browserverlauf und Lesezeichen lesen"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ermöglicht der Anwendung, alle URLs, die mit dem Browser besucht wurden, sowie alle Lesezeichen des Browsers zu lesen."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Browserverlauf und Lesezeichen schreiben"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Neuer Kontakt"\n"mit <xliff:g id="NUMBER">%s</xliff:g> erstellen"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"aktiviert"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"nicht aktiviert"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Die aufgelisteten Anwendungen fordern eine Berechtigung zum Zugriff auf die Anmeldeinformationen für das Konto <xliff:g id="ACCOUNT">%1$s</xliff:g> von <xliff:g id="APPLICATION">%2$s</xliff:g> an. Möchten Sie diese Berechtigung erteilen? Wenn ja, wird Ihre Antwort gespeichert und Sie erhalten keine erneute Aufforderung."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Die aufgelisteten Anwendungen fordern eine Berechtigung zum Zugriff auf die <xliff:g id="TYPE">%1$s</xliff:g>-Anmeldeinformationen für das Konto <xliff:g id="APPLICATION">%3$s</xliff:g> von <xliff:g id="ACCOUNT">%2$s</xliff:g> an. Möchten Sie diese Berechtigung erteilen? Wenn ja, wird Ihre Antwort gespeichert und Sie erhalten keine erneute Aufforderung."</string>
     <string name="allow" msgid="7225948811296386551">"Zulassen"</string>
     <string name="deny" msgid="2081879885755434506">"Ablehnen"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Berechtigung angefordert"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Eingabehilfen"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hintergrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Hintergrundbild ändern"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 23c6565..a4ec8c1 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Παρακολούθηση της φυσικής τοποθεσίας σας"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Επικοινωνία δικτύου"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Επιτρέπει σε εφαρμογές να αποκτήσουν πρόσβαση σε διάφορες λειτουργίες δικτύου."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Οι λογαριασμοί σας Google"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Πρόσβαση στους διαθέσιμους λογαριασμούς Google."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Στοιχεία ελέγχου υλικού"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Άμεση πρόσβαση στο υλικό της συσκευής τηλεφώνου."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Τηλεφωνικές κλήσεις"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Πληκτρολογήστε τον κωδικό αριθμό PIN"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Εσφαλμένος κωδικός αριθμός PIN!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Για ξεκλείδωμα, πατήστε το πλήκτρο Menu και, στη συνέχεια, το πλήκτρο 0."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Προσπαθήστε αργότερα"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Φόρτιση (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Φορτίστηκε."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Συνδέστε τον φορτιστή."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Δεν υπάρχει κάρτα SIM."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Δεν υπάρχει κάρτα SIM στο τηλέφωνο."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Φόρτιση..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Συνδέστε τον φορτιστή"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Η στάθμη της μπαταρίας είναι χαμηλή:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"απομένουν λιγότερο από <xliff:g id="NUMBER">%d%%</xliff:g>."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Χρήση μπαταρίας"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Η εργοστασιακή δοκιμή απέτυχε"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Η ενέργεια FACTORY_TEST υποστηρίζεται μόνο για πακέτα που είναι εγκατεστημένα στον κατάλογο /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Απομάκρυνση από αυτή τη σελίδα;"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Επιλέξτε OK για συνέχεια, ή Ακύρωση για παραμονή στην τρέχουσα σελίδα."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Επιβεβαίωση"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ανάγνωση ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Επιτρέπει στην εφαρμογή την ανάγνωση όλων των διευθύνσεων URL που το πρόγραμμα περιήγησης έχει επισκεφθεί και όλων των σελιδοδεικτών του προγράμματος περιήγησης."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"εγγραφή ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Δημιουργία επαφής"\n"με τη χρήση του <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"επιλεγμένο"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"δεν ελέγχθηκε"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Οι εφαρμογές που παραθέτονται στη λίστα ζητούν άδεια για να αποκτήσουν πρόσβαση στα διαπιστευτήρια σύνδεσης για τον λογαριασμό <xliff:g id="ACCOUNT">%1$s</xliff:g> από <xliff:g id="APPLICATION">%2$s</xliff:g>. Θα αποδεχτείτε το αίτημα; Εάν το αποδεχτείτε, η απάντησή σας θα αποθηκευτεί και δεν θα ερωτηθείτε ξανά."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Οι εφαρμογές που παραθέτονται στη λίστα ζητούν άδεια για να αποκτήσουν πρόσβαση στα διαπιστευτήρια σύνδεσης <xliff:g id="TYPE">%1$s</xliff:g> για τον λογαριασμό <xliff:g id="ACCOUNT">%2$s</xliff:g> από <xliff:g id="APPLICATION">%3$s</xliff:g>. Θα αποδεχτείτε το αίτημα; Εάν το αποδεχτείτε, η απάντησή σας θα αποθηκευτεί και δεν θα ερωτηθείτε ξανά."</string>
     <string name="allow" msgid="7225948811296386551">"Να επιτρέπεται"</string>
     <string name="deny" msgid="2081879885755434506">"Άρνηση"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Απαιτείται άδεια"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Προσβασιμότητα"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ταπετσαρία"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Αλλαγή ταπετσαρίας"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index e2059d8..025ae60 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -111,8 +111,7 @@
     <string name="httpErrorFile" msgid="8250549644091165175">"No se ha podido acceder al archivo."</string>
     <string name="httpErrorFileNotFound" msgid="5588380756326017105">"No se ha encontrado el archivo solicitado."</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Se están procesando demasiadas solicitudes. Vuelve a intentarlo más tarde."</string>
-    <!-- no translation found for notification_title (1259940370369187045) -->
-    <skip />
+    <string name="notification_title" msgid="1259940370369187045">"Error al iniciar la sesión de <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
     <string name="contentServiceSync" msgid="8353523060269335667">"Sincronización"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronización"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Demasiadas eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g>"</string>
@@ -148,8 +147,8 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Controla tu ubicación física"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicación de red"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Admite aplicaciones que acceden a varias funciones de red."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Tus cuentas de Google"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Acceder a las cuentas disponibles de Google."</string>
+    <string name="permgrouplab_accounts" msgid="3359646291125325519">"Tus cuentas"</string>
+    <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Acceder a las cuentas disponibles."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controles de hardware"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Acceso directo al hardware en el teléfono."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Llamadas telefónicas"</string>
@@ -433,6 +432,58 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <string name="phoneTypeCustom" msgid="1644738059053355820">"Personalizado"</string>
+    <string name="phoneTypeHome" msgid="2570923463033985887">"Página principal"</string>
+    <string name="phoneTypeMobile" msgid="6501463557754751037">"Celular"</string>
+    <string name="phoneTypeWork" msgid="8863939667059911633">"Trabajo"</string>
+    <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Fax laboral"</string>
+    <string name="phoneTypeFaxHome" msgid="2067265972322971467">"Fax personal"</string>
+    <string name="phoneTypePager" msgid="7582359955394921732">"Localizador"</string>
+    <string name="phoneTypeOther" msgid="1544425847868765990">"Otro"</string>
+    <string name="phoneTypeCallback" msgid="2712175203065678206">"Devolución de llamada"</string>
+    <string name="phoneTypeCar" msgid="8738360689616716982">"Automóvil"</string>
+    <string name="phoneTypeCompanyMain" msgid="540434356461478916">"Empresa principal"</string>
+    <string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
+    <string name="phoneTypeMain" msgid="6766137010628326916">"Principal"</string>
+    <string name="phoneTypeOtherFax" msgid="8587657145072446565">"Otro fax"</string>
+    <string name="phoneTypeRadio" msgid="4093738079908667513">"Radio"</string>
+    <string name="phoneTypeTelex" msgid="3367879952476250512">"Télex"</string>
+    <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
+    <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Celular del trabajo"</string>
+    <string name="phoneTypeWorkPager" msgid="649938731231157056">"Localizador del trabajo"</string>
+    <string name="phoneTypeAssistant" msgid="5596772636128562884">"Asistente"</string>
+    <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
+    <string name="eventTypeBirthday" msgid="2813379844211390740">"Cumpleaños"</string>
+    <string name="eventTypeAnniversary" msgid="3876779744518284000">"Aniversario"</string>
+    <string name="eventTypeOther" msgid="5834288791948564594">"Evento"</string>
+    <string name="emailTypeCustom" msgid="8525960257804213846">"Personalizado"</string>
+    <string name="emailTypeHome" msgid="449227236140433919">"Página principal"</string>
+    <string name="emailTypeWork" msgid="3548058059601149973">"Trabajo"</string>
+    <string name="emailTypeOther" msgid="2923008695272639549">"Otro"</string>
+    <string name="emailTypeMobile" msgid="119919005321166205">"Celular"</string>
+    <string name="postalTypeCustom" msgid="8903206903060479902">"Personalizado"</string>
+    <string name="postalTypeHome" msgid="8165756977184483097">"Página principal"</string>
+    <string name="postalTypeWork" msgid="5268172772387694495">"Trabajo"</string>
+    <string name="postalTypeOther" msgid="2726111966623584341">"Otro"</string>
+    <string name="imTypeCustom" msgid="2074028755527826046">"Personalizado"</string>
+    <string name="imTypeHome" msgid="6241181032954263892">"Página principal"</string>
+    <string name="imTypeWork" msgid="1371489290242433090">"Trabajo"</string>
+    <string name="imTypeOther" msgid="5377007495735915478">"Otro"</string>
+    <string name="imProtocolCustom" msgid="6919453836618749992">"Personalizado"</string>
+    <string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
+    <string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
+    <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string>
+    <string name="imProtocolSkype" msgid="9019296744622832951">"Skype"</string>
+    <string name="imProtocolQq" msgid="8887484379494111884">"QQ"</string>
+    <string name="imProtocolGoogleTalk" msgid="3808393979157698766">"Google Talk"</string>
+    <string name="imProtocolIcq" msgid="1574870433606517315">"ICQ"</string>
+    <string name="imProtocolJabber" msgid="2279917630875771722">"Jabber"</string>
+    <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
+    <string name="orgTypeWork" msgid="29268870505363872">"Trabajo"</string>
+    <string name="orgTypeOther" msgid="3951781131570124082">"Otro"</string>
+    <string name="orgTypeCustom" msgid="225523415372088322">"Personalizado"</string>
+    <string name="contact_status_update_attribution" msgid="5112589886094402795">"a través de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+    <string name="contact_status_update_attribution_with_date" msgid="5945386376369979909">"<xliff:g id="DATE">%1$s</xliff:g> a través de <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ingresar el código de PIN"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"¡Código de PIN incorrecto!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Para desbloquear, presiona el menú y luego 0."</string>
@@ -447,6 +498,7 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Lo sentimos, vuelve a intentarlo"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Cargada."</string>
+    <string name="lockscreen_battery_short" msgid="3617549178603354656">"Segmento <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta tu cargador."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"No hay tarjeta SIM."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"No hay tarjeta SIM en el teléfono."</string>
@@ -478,7 +530,7 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Cargando..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Conecta el cargador"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Hay poca batería:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"menos de <xliff:g id="NUMBER">%d%%</xliff:g> restante."</string>
+    <string name="battery_low_percent_format" msgid="696154104579022959">"Restan <xliff:g id="NUMBER">%d%%</xliff:g> o menos."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Uso de la batería"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Error en la prueba de fábrica"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"La acción FACTORY_TEST se admite solamente en paquetes instalados en /system/app."</string>
@@ -488,6 +540,7 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"¿Deseas salir de esta página?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Selecciona Aceptar para continuar o Cancelar para permanecer en la página actual."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Confirmar"</string>
+    <string name="double_tap_toast" msgid="1068216937244567247">"Sugerencia: presiona dos veces para acercar y alejar"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"leer historial y marcadores del navegador"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite a la aplicación leer todas las URL que ha visitado el navegador y todos los marcadores del navegador."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escribir historial y marcadores del navegador"</string>
@@ -692,10 +745,8 @@
     <string name="extmedia_format_message" msgid="3621369962433523619">"¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de tu tarjeta."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formato"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración de USB conectada"</string>
-    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
-    <skip />
-    <!-- no translation found for select_input_method (6865512749462072765) -->
-    <skip />
+    <string name="adb_active_notification_message" msgid="8470296818270110396">"Seleccionar para desactivar la depuración de USB."</string>
+    <string name="select_input_method" msgid="6865512749462072765">"Seleccionar método de entrada"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
@@ -726,16 +777,17 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Crear contacto "\n"con <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"verificado"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"no verificado"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Las aplicaciones enumeradas requieren permiso para acceder a las credenciales de inicio de sesión para la cuenta <xliff:g id="ACCOUNT">%1$s</xliff:g> desde <xliff:g id="APPLICATION">%2$s</xliff:g> ¿Deseas otorgar este permiso? Si es así, el sistema recordará tu respuesta y no volverá a solicitarla."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Las aplicaciones enumeradas requieren permiso para acceder a las <xliff:g id="TYPE">%1$s</xliff:g> credenciales de inicio de sesión para la cuenta <xliff:g id="ACCOUNT">%2$s</xliff:g> desde <xliff:g id="APPLICATION">%3$s</xliff:g>.¿Deseas otorgar este permiso? Si es así, el sistema recordará tu respuesta y no volverá a solicitarla."</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Denegar"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Permiso solicitado"</string>
-    <!-- no translation found for permission_request_notification_with_subtitle (4325409589686688000) -->
-    <skip />
+    <string name="permission_request_notification_with_subtitle" msgid="4325409589686688000">"Permiso solicitado"\n"para la cuenta <xliff:g id="ACCOUNT">%s</xliff:g>"</string>
     <string name="input_method_binding_label" msgid="1283557179944992649">"Método de entrada"</string>
     <string name="sync_binding_label" msgid="3687969138375092423">"Sincronización"</string>
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilidad"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Papel tapiz"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
+    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocolo de túnel punto a punto"</string>
+    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de túnel de nivel 2"</string>
+    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Clave previamente compartida según L2TP/IPSec VPN"</string>
+    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certificado según L2TP/IPSec VPN"</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 74f7e11..ebe1bb0 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Controlar su ubicación física"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicación de red"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Permite que las aplicaciones accedan a distintas funciones de red."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Tus cuentas de Google"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Acceder a las cuentas de Google disponibles"</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controles de hardware"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Acceso directo al hardware del móvil"</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Llamadas de teléfono"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduce el código PIN"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"El código PIN es incorrecto."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Para desbloquear el teléfono, pulsa la tecla de menú y, a continuación, pulsa 0."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Inténtalo de nuevo"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Cargado"</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta el cargador"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Falta la tarjeta SIM"</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"No se ha insertado ninguna tarjeta SIM en el teléfono."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Cargando..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Conecta el cargador"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Se está agotando la batería:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"menos del <xliff:g id="NUMBER">%d%%</xliff:g> disponible."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Uso de la batería"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Fallo en la prueba de fábrica"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"La acción FACTORY_TEST sólo es compatible con los paquetes instalados en /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"¿Quieres salir de esta página?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Selecciona \"Aceptar\" para continuar o \"Cancelar\" para permanecer en la página actual."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Confirmar"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"leer información de marcadores y del historial del navegador"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que la aplicación lea todas las URL que ha visitado el navegador y todos sus marcadores."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escribir en marcadores y en el historial del navegador"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Crear un contacto"\n"a partir de <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"seleccionado"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"no seleccionado"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Las aplicaciones de la lista están solicitando permiso para acceder a las credenciales de acceso de la cuenta <xliff:g id="ACCOUNT">%1$s</xliff:g> desde <xliff:g id="APPLICATION">%2$s</xliff:g>. ¿Deseas conceder este permiso? En tal caso, se recordará tu respuesta y no se te volverá a preguntar."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Las aplicaciones de la lista están solicitando permiso para acceder a las credenciales de acceso (<xliff:g id="TYPE">%1$s</xliff:g>) de la cuenta <xliff:g id="ACCOUNT">%2$s</xliff:g> desde <xliff:g id="APPLICATION">%3$s</xliff:g>. ¿Deseas conceder este permiso? En tal caso, se recordará tu respuesta y no se te volverá a preguntar."</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Denegar"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Permiso solicitado"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilidad"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fondo de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index c0f59f2..5647063 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Suivre votre position géographique"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Communications réseau"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Permet à des applications d\'accéder à différentes fonctionnalités du réseau."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Vos comptes Google"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Accédez aux comptes Google disponibles."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Commandes du matériel"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Permet d\'accéder directement au matériel de l\'appareil."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Appels"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Saisissez le code PIN"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Le code PIN est incorrect !"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Pour débloquer le clavier, appuyez sur \"Menu\" puis sur 0."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Désolé. Merci de réessayer."</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Chargement (<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Chargé"</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Branchez votre chargeur."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Aucune carte SIM n\'a été trouvée."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Aucune carte SIM n\'est insérée dans le téléphone."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Chargement..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Branchez le chargeur"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Le niveau de la batterie est bas :"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"Batterie restante inférieure à <xliff:g id="NUMBER">%d%%</xliff:g>."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Utilisation de la batterie"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Échec du test usine"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"L\'action FACTORY_TEST est uniquement prise en charge pour les paquets de données installés dans in/system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Vous souhaitez quitter cette page ?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Sélectionnez OK pour continuer ou Annuler pour rester sur la page actuelle."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Confirmer"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lire l\'historique et les favoris du navigateur"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Autorise l\'application à lire toutes les URL auxquelles le navigateur a accédé et tous ses favoris."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"écrire dans l\'historique et les favoris du navigateur"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Ajouter un contact"\n"en utilisant <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"sélectionné"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"non sélectionné"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Les applications répertoriées demandent l\'autorisation d\'accéder aux informations d\'identification du compte <xliff:g id="ACCOUNT">%1$s</xliff:g> depuis <xliff:g id="APPLICATION">%2$s</xliff:g>. Souhaitez-vous accorder cette autorisation ? Si vous acceptez, votre choix sera enregistré et cette question ne vous sera plus posée."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Les applications répertoriées demandent l\'autorisation d\'accéder aux informations d\'identification des <xliff:g id="TYPE">%1$s</xliff:g> associés au compte <xliff:g id="ACCOUNT">%2$s</xliff:g> depuis <xliff:g id="APPLICATION">%3$s</xliff:g>. Souhaitez-vous accorder cette autorisation ? Si vous acceptez, votre choix sera enregistré et cette question ne vous sera plus posée."</string>
     <string name="allow" msgid="7225948811296386551">"Autoriser"</string>
     <string name="deny" msgid="2081879885755434506">"Refuser"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Autorisation demandée"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilité"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fond d\'écran"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Changer de fond d\'écran"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d62625f..f0647e7 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -133,7 +133,7 @@
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modalità silenziosa"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Audio non attivo"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Audio attivo"</string>
-    <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modalità aereo attiva"</string>
+    <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modalità aereo"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modalità aereo attiva"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modalità aereo non attiva"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Monitorare la posizione fisica dell\'utente"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicazione di rete"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Consentono l\'accesso delle applicazioni a varie funzionalità di rete."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"I tuoi account Google"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Accedere agli account Google disponibili."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controlli hardware"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Accedere direttamente all\'hardware del ricevitore."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Telefonate"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Inserisci il PIN"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Codice PIN errato."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Per sbloccare, premi Menu, poi 0."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Riprova"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"In carica (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Carico."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Collegare il caricabatterie."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nessuna SIM presente."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Nessuna SIM presente nel telefono."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"In carica..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Collegare il caricabatterie"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteria quasi scarica:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"energia residua inferiore a <xliff:g id="NUMBER">%d%%</xliff:g>."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Utilizzo batteria"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Test di fabbrica non riuscito"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"L\'azione FACTORY_TEST è supportata soltanto per i pacchetti installati in /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Uscire da questa pagina?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Seleziona OK per continuare o Annulla per rimanere nella pagina corrente."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Conferma"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lettura cronologia e segnalibri del browser"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Consente all\'applicazione di leggere tutti gli URL visitati e tutti i segnalibri del browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"creazione cronologia e segnalibri del browser"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Crea contatto"\n"utilizzando <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"selezionato"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"non selezionato"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Le applicazioni elencate richiedono l\'autorizzazione per accedere alle credenziali di accesso per l\'account <xliff:g id="ACCOUNT">%1$s</xliff:g> da <xliff:g id="APPLICATION">%2$s</xliff:g>. Concedere questa autorizzazione? In tal caso la tua risposta verrà memorizzata e questa domanda non ti verrà più posta."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Le applicazioni elencate richiedono l\'autorizzazione per accedere alle credenziali di accesso <xliff:g id="TYPE">%1$s</xliff:g> per l\'account <xliff:g id="ACCOUNT">%2$s</xliff:g> da <xliff:g id="APPLICATION">%3$s</xliff:g>. Concedere questa autorizzazione? In tal caso la tua risposta verrà memorizzata e questa domanda non ti verrà più posta."</string>
     <string name="allow" msgid="7225948811296386551">"Consenti"</string>
     <string name="deny" msgid="2081879885755434506">"Nega"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Autorizzazione richiesta"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesso facilitato"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Sfondo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambia sfondo"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 55e6b50..9517af5 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"現在地を追跡"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"ネットワーク通信"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"ネットワークのさまざまな機能へのアクセスをアプリケーションに許可します。"</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Googleアカウント"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"利用可能なGoogleアカウントへのアクセス"</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"ハードウェアの制御"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"携帯電話のハードウェアに直接アクセスします。"</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"電話/通話"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PINコードを入力"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"PINコードが正しくありません。"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"MENU、0キーでロック解除"</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"やり直してください"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"充電中(<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"充電完了。"</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"充電してください。"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIMカードが挿入されていません"</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"SIMカードが挿入されていません"</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"充電中..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"充電してください"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"電池が残り少なくなっています:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"残量<xliff:g id="NUMBER">%d%%</xliff:g>以下"</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"電池使用量"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"出荷時試験が失敗"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST操作は、/system/appにインストールされたパッケージのみが対象です。"</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"このページから移動しますか?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"移動する場合は[OK]、今のページに残る場合は[キャンセル]を選択してください。"</string>
     <string name="save_password_label" msgid="6860261758665825069">"確認"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ブラウザの履歴とブックマークを読み取る"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"ブラウザでアクセスしたすべてのURLおよびブラウザのすべてのブックマークの読み取りをアプリケーションに許可します。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"ブラウザの履歴とブックマークを書き込む"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"<xliff:g id="NUMBER">%s</xliff:g>を使って"\n"連絡先を新規登録"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"オン"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"オフ"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"リストされているアプリケーションが、アカウント<xliff:g id="ACCOUNT">%1$s</xliff:g>のログイン認証情報に<xliff:g id="APPLICATION">%2$s</xliff:g>からアクセスする権限をリクエストしています。この権限を許可しますか?許可すると、入力が記録され、次回以降はこのメッセージが表示されなくなります。"</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"リストされているアプリケーションが、アカウント<xliff:g id="ACCOUNT">%2$s</xliff:g>の<xliff:g id="TYPE">%1$s</xliff:g>ログイン認証情報に<xliff:g id="APPLICATION">%3$s</xliff:g>からアクセスする権限をリクエストしています。この権限を許可しますか?許可すると、入力は記録され、次回以降はこのメッセージが表示されなくなります。"</string>
     <string name="allow" msgid="7225948811296386551">"許可"</string>
     <string name="deny" msgid="2081879885755434506">"拒否"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"リクエスト済み権限"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"アクセシビリティ"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁紙"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"壁紙を変更"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 3db36fc..0ef3824 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"실제 위치 모니터링"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"네트워크 통신"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"응용프로그램이 다양한 네트워크 기능에 액세스할 수 있도록 합니다."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Google 계정"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"사용 가능한 Google 계정에 액세스합니다."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"하드웨어 제어"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"휴대전화의 하드웨어에 직접 액세스합니다."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"전화 통화"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN 코드 입력"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"PIN 코드가 잘못되었습니다."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"잠금해제하려면 메뉴를 누른 다음 0을 누릅니다."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"죄송합니다. 다시 시도하세요."</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"충전 중(<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"충전되었습니다."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"충전기를 연결하세요."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIM 카드가 없습니다."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"휴대전화에 SIM 카드가 없습니다."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"충전 중..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"충전기를 연결하세요."</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"배터리 전원이 부족합니다."</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"<xliff:g id="NUMBER">%d%%</xliff:g> 미만 남음"</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"배터리 사용"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"출고 테스트 불합격"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST 작업은 /system/app 디렉토리에 설치된 패키지에 대해서만 지원됩니다."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"자바스크립트"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"다른 페이지를 탐색하시겠습니까?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"계속하려면 \'확인\'을 선택하고 현재 페이지에 그대로 있으려면 \'취소\'를 선택하세요."</string>
     <string name="save_password_label" msgid="6860261758665825069">"확인"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"브라우저의 기록 및 북마크 읽기"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"응용프로그램이 브라우저로 방문한 모든 URL과 브라우저의 모든 북마크를 읽도록 허용합니다."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"브라우저의 기록 및 북마크 쓰기"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"전화번호부에"\n"<xliff:g id="NUMBER">%s</xliff:g> 추가"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"선택함"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"선택 안함"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"나열된 응용프로그램이 <xliff:g id="APPLICATION">%2$s</xliff:g>에서 <xliff:g id="ACCOUNT">%1$s</xliff:g> 계정의 로그인 자격증명에 액세스할 수 있는 권한을 요청 중입니다. 권한을 부여하시겠습니까? 권한을 부여하면 응답 내용이 저장되며 메시지가 다시 표시되지 않습니다."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"나열된 응용프로그램이 <xliff:g id="APPLICATION">%3$s</xliff:g>에서 <xliff:g id="ACCOUNT">%2$s</xliff:g> 계정의 <xliff:g id="TYPE">%1$s</xliff:g> 로그인 자격증명에 액세스할 수 있는 권한을 요청 중입니다. 권한을 부여하시겠습니까? 권한을 부여하면 응답 내용이 저장되며 메시지가 다시 표시되지 않습니다."</string>
     <string name="allow" msgid="7225948811296386551">"허용"</string>
     <string name="deny" msgid="2081879885755434506">"거부"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"권한 요청"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"접근성"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"배경화면"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"배경화면 변경"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 19524d8..aa15ad1 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Overvåking av telefonens fysiske plassering"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Nettverkstilgang"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Gir applikasjoner tilgang til diverse nettverksfunksjoner."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Google-kontoer"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Tilgang til tilgjengelige Google-kontoer."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Maskinvarekontroll"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Direkte tilgang til maskinvaren på telefonen."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Telefonsamtaler"</string>
@@ -196,7 +198,7 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Lar applikasjonen sette aktivitetshåndtereren i avslutningstilstand. Slår ikke systemet helt av."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"forhindre applikasjonsbytte"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Lar applikasjonen forhindre brukeren fra å bytte til en annen applikasjon."</string>
-    <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"overvåke og kontrollere all applikasjonsoppstart"</string>
+    <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"Blokker popup-vinduer"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="3228701938345388092">"Lar applikasjonen overvåke og kontrollere hvordan systemet starter applikasjoner. Ondsinnede applikasjoner kan ta over systemet helt. Denne rettigheten behøves bare for utvikling, aldri for vanlig bruk av telefonen."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"kringkaste melding om fjernet pakke"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Lar applikasjonen kringkaste en melding om at en applikasjonspakke er blitt fjernet. Ondsinnede applikasjoner kan bruke dette til å drepe vilkårlige andre kjørende applikasjoner."</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Skriv inn PIN-kode:"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Gal PIN-kode!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"For å låse opp, trykk på menyknappen og deretter 0."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Beklager, prøv igjen:"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Lader (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Fullt ladet"</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Koble til en batterilader."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Mangler SIM-kort."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Ikke noe SIM-kort i telefonen."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Lader…"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Koble til en lader"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteriet er nesten tomt:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"mindre enn <xliff:g id="NUMBER">%d%%</xliff:g> igjen."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Batteribruk"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Factory test failed"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"The FACTORY_TEST action is only supported for packages installed in /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Naviger bort fra denne siden?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Velg OK for å fortsette, eller Avbryt for å forbli på denne siden."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Bekreft"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lese nettleserens logg og bokmerker"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Lar applikasjonen lese alle adresser nettleseren har besøkt, og alle nettleserens bokmerker."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skrive til nettleserens logg og bokmerker"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Lag kontakt"\n"med nummeret <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"valgt"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"ikke valgt"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Det nevnte programmet ber om tilgangstillatelse til påloggingsopplysningene for konto <xliff:g id="ACCOUNT">%1$s</xliff:g> fra <xliff:g id="APPLICATION">%2$s</xliff:g>. Vil du gi denne tillatelsen? I så fall vil svaret ditt bli lagret, og du vil ikke bli spurt flere ganger."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Det nevnte programmet ber om tilgangstillatelse til <xliff:g id="TYPE">%1$s</xliff:g>-påloggingsopplysningene for konto <xliff:g id="ACCOUNT">%2$s</xliff:g> fra <xliff:g id="APPLICATION">%3$s</xliff:g>. Vil du gi denne tillatelsen? I så fall vil svaret ditt bli lagret, og du vil ikke bli spurt flere ganger."</string>
     <string name="allow" msgid="7225948811296386551">"Tillat"</string>
     <string name="deny" msgid="2081879885755434506">"Avslå"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Tillatelse forespurt"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Tilgjengelighet"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrunnsbilde"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Endre bakgrunnsbilde"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 085a99c..c299ef8 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Uw fysieke locatie bijhouden"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Netwerkcommunicatie"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Toepassingen toestaan verschillende netwerkfuncties te openen."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Uw Google-accounts"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Toegang tot de beschikbare Google-accounts."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Bedieningselementen hardware"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Rechtstreekse toegang tot hardware op de handset."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Telefoonoproepen"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN-code invoeren"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Onjuiste PIN-code!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Druk op \'Menu\' en vervolgens op 0 om te ontgrendelen."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Probeer het opnieuw"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Opladen (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Opgeladen."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Sluit de oplader aan."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Geen SIM-kaart."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Geen SIM-kaart in telefoon."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Opladen..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Sluit de oplader aan"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"De accu raakt op:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"minder dan <xliff:g id="NUMBER">%d%%</xliff:g> resterend."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Accugebruik"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Fabriekstest mislukt"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"De actie FACTORY_TEST wordt alleen ondersteund voor pakketten die zijn geïnstalleerd in /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Wilt u deze pagina verlaten?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Kies OK om door te gaan of Annuleren om op de huidige pagina te blijven."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Bevestigen"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"browsergeschiedenis en bladwijzers lezen"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Hiermee kan een toepassing de URL\'s lezen die u via de browser heeft bezocht, evenals alle bladwijzers van de browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"browsergeschiedenis en bladwijzers schrijven"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Contact maken"\n"met <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"aangevinkt"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"niet aangevinkt"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"De weergegeven toepassingen vragen toestemming voor toegang tot de aanmeldingsgegevens voor account \'<xliff:g id="ACCOUNT">%1$s</xliff:g>\' van <xliff:g id="APPLICATION">%2$s</xliff:g>. Wilt u deze toestemming verlenen? Als u dit wilt doen, wordt uw antwoord onthouden en wordt dit niet opnieuw gevraagd."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"De weergegeven toepassingen vragen toestemming voor toegang tot de aanmeldingsgegevens voor <xliff:g id="TYPE">%1$s</xliff:g> van het account \'<xliff:g id="ACCOUNT">%2$s</xliff:g>\' van <xliff:g id="APPLICATION">%3$s</xliff:g>. Wilt u deze toestemming verlenen? Als u dit wilt doen, wordt uw antwoord onthouden en wordt dit niet opnieuw gevraagd."</string>
     <string name="allow" msgid="7225948811296386551">"Toestaan"</string>
     <string name="deny" msgid="2081879885755434506">"Weigeren"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Toestemming gevraagd"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Toegankelijkheid"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Achtergrond"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Achtergrond wijzigen"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 145deda..f53bd4c5 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Monitorowanie fizycznej lokalizacji"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Połączenia sieciowe"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Pozwól aplikacjom na dostęp do różnych funkcji sieci."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Twoje konta Google"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Uzyskaj dostęp do dostępnych kont Google."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Sterowanie sprzętowe"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Bezpośredni dostęp do elementów sprzętowych telefonu."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Połączenia telefoniczne"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Wprowadź kod PIN"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Błędny kod PIN!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Aby odblokować, naciśnij Menu, a następnie 0."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Niestety, spróbuj ponownie"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Ładowanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Naładowany."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Podłącz ładowarkę."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Brak karty SIM."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Brak karty SIM w telefonie."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Ładowanie..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Podłącz ładowarkę"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Bateria się rozładowuje:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"pozostało mniej niż <xliff:g id="NUMBER">%d%%</xliff:g>."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Użycie baterii"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Nieudany test fabryczny"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Czynność FACTORY_TEST jest obsługiwana tylko dla pakietów zainstalowanych w katalogu /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Czy opuścić tę stronę?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Wybierz opcję OK, aby kontynuować, lub opcję Anuluj, aby pozostać na tej stronie."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Potwierdź"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"odczyt historii i zakładek przeglądarki"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umożliwia aplikacji odczyt wszystkich adresów URL odwiedzonych przez przeglądarkę, a także wszystkich zakładek przeglądarki."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"zapis historii i zakładek przeglądarki"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Utwórz kontakt"\n"dla numeru <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"zaznaczone"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"niezaznaczone"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Wymienione aplikacje żądają pozwolenia na dostęp do danych logowania dla konta <xliff:g id="ACCOUNT">%1$s</xliff:g> powiązanego z aplikacją <xliff:g id="APPLICATION">%2$s</xliff:g>. Czy chcesz udzielić takiego pozwolenia? Jeśli tak, odpowiedź zostanie zapamiętana i to pytanie nie będzie już wyświetlane."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Wymienione aplikacje żądają pozwolenia na dostęp do danych logowania dotyczących funkcji <xliff:g id="TYPE">%1$s</xliff:g> dla konta <xliff:g id="ACCOUNT">%2$s</xliff:g> powiązanego z aplikacją <xliff:g id="APPLICATION">%3$s</xliff:g>. Czy chcesz udzielić takiego pozwolenia? Jeśli tak, odpowiedź zostanie zapamiętana i to pytanie nie będzie już wyświetlane."</string>
     <string name="allow" msgid="7225948811296386551">"Zezwól"</string>
     <string name="deny" msgid="2081879885755434506">"Odmów"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Żądane pozwolenie"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Ułatwienia dostępu"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmień tapetę"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 4e9a0a8..891e7ce 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Monitorizar a sua localização física"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicação de rede"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Permite o acesso de aplicações a várias funcionalidades de rede."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"As suas Contas Google"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Aceda às Contas Google disponíveis."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controlos de hardware"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Aceda directamente ao hardware no telefone."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Chamadas"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduzir código PIN"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Código PIN incorrecto!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Para desbloquear, prima Menu e, em seguida, 0."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Lamentamos, tente novamente"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"A carregar (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Carregado."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ligue o carregador."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nenhum cartão SIM."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Nenhum cartão SIM no telefone."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"A carregar..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Ligue o carregador"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"A bateria está a ficar fraca:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"resta menos de <xliff:g id="NUMBER">%d%%</xliff:g>."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Utilização da bateria"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"O teste de fábrica falhou"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"A acção FACTORY_TEST apenas é suportada para pacotes instalados em /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Navegar para outra página?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Seleccione OK para continuar ou Cancelar para permanecer na página actual."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Confirmar"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ler histórico e marcadores do browser"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que a aplicação leia todos os URLs visitados pelo browser e todos os marcadores do browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"gravar histórico e marcadores do browser"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Criar contacto"\n"utilizando <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"verificado"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"não verificado"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"As aplicações listadas estão a pedir autorização para aceder às credenciais de início de sessão da conta <xliff:g id="ACCOUNT">%1$s</xliff:g> a partir de <xliff:g id="APPLICATION">%2$s</xliff:g>. Pretende conceder esta autorização? Em caso afirmativo, a sua resposta será memorizada e não lhe será solicitado que responda novamente."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"As aplicações listadas estão a pedir autorização para aceder às credenciais de início de sessão <xliff:g id="TYPE">%1$s</xliff:g> para a conta <xliff:g id="ACCOUNT">%2$s</xliff:g> a partir de <xliff:g id="APPLICATION">%3$s</xliff:g>. Pretende conceder esta autorização? Em caso afirmativo, a sua resposta será memorizada e não lhe será solicitado que responda novamente."</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Recusar"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Autorização Solicitada"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Acessibilidade"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagem de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar imagem de fundo"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 72990a1..265fb62 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Monitora o seu local físico."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicação da rede"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Permite que os aplicativos acessem diversos recursos de rede."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Suas Contas do Google"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Acessar as Contas do Google disponíveis."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controles de hardware"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Acessa o hardware diretamente no aparelho."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Chamadas telefônicas"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Digite o código PIN"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Código PIN incorreto!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Para desbloquear, pressione Menu e, em seguida, 0."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Tente novamente"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Carregando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Carregado."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecte o seu carregador."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Sem cartão SIM."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Não há um cartão SIM no telefone."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Carregando..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Conecte o carregador"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"A bateria está ficando baixa:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"menos de <xliff:g id="NUMBER">%d%%</xliff:g> restantes."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Uso da bateria"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Falha no teste de fábrica"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"A ação FACTORY_TEST é suportada apenas para pacotes instalados em /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Deseja sair desta página?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Selecione OK para continuar ou Cancelar para permanecer na página atual."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Confirmar"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ler histórico e favoritos do Navegador"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que o aplicativo leia todos os URLs visitados pelo Navegador e todos os favoritos do Navegador."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"gravar histórico e favoritos do Navegador"</string>
@@ -585,7 +696,7 @@
     <string name="weeks" msgid="6509623834583944518">"semanas"</string>
     <string name="year" msgid="4001118221013892076">"ano"</string>
     <string name="years" msgid="6881577717993213522">"anos"</string>
-    <string name="every_weekday" msgid="8777593878457748503">"Todos os dias da semana (de segunda a sexta)"</string>
+    <string name="every_weekday" msgid="8777593878457748503">"De segunda a sexta-feira"</string>
     <string name="daily" msgid="5738949095624133403">"Diariamente"</string>
     <string name="weekly" msgid="983428358394268344">"Semanalmente na <xliff:g id="DAY">%s</xliff:g>"</string>
     <string name="monthly" msgid="2667202947170988834">"Mensalmente"</string>
@@ -719,15 +830,13 @@
     <string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
     <string name="ime_action_search" msgid="658110271822807811">"Pesquisar"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"Enviar"</string>
-    <string name="ime_action_next" msgid="3138843904009813834">"Próximo"</string>
+    <string name="ime_action_next" msgid="3138843904009813834">"Avançar"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Concluído"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Executar"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Discar número"\n"usando <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Criar contato "\n"usando <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"selecionado"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"não selecionado"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Os aplicativos listados estão solicitando autorização para acessar as credenciais de login para a conta <xliff:g id="ACCOUNT">%1$s</xliff:g> de <xliff:g id="APPLICATION">%2$s</xliff:g>. Deseja conceder essa autorização? Em caso afirmativo, sua resposta será lembrada e essa pergunta não será feita novamente."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Os aplicativos listados estão solicitando autorização para acessar as credenciais de login <xliff:g id="TYPE">%1$s</xliff:g> para a conta <xliff:g id="ACCOUNT">%2$s</xliff:g> de <xliff:g id="APPLICATION">%3$s</xliff:g>. Deseja conceder essa autorização? Em caso afirmativo, sua resposta será lembrada e essa pergunta não será feita novamente."</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Negar"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Autorização solicitada"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Acessibilidade"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Papel de parede"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar papel de parede"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index a286312..373c45e 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Отслеживание физического местоположения"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Сетевой обмен данными"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Позволяет приложениям получать доступ к различным сетевым функциям."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Ваши аккаунты Google"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Входить в доступные аккаунты Google."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Элементы управления аппаратным обеспечением"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Прямой доступ к аппаратному обеспечению телефона."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Телефонные вызовы"</string>
@@ -388,7 +390,7 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Позволяет приложению считывать любые слова, имена и фразы личного пользования, которые могут храниться в пользовательском словаре."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"записывать в пользовательский словарь"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Позволяет приложению записывать новые слова в пользовательский словарь."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"изменить/удалить содержание SD-карты"</string>
+    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"изменять/удалять содержание SD-карты"</string>
     <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Разрешает приложению запись на SD-карту"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Домашний"</item>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Введите PIN-код"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Неверный PIN-код!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Для разблокировки нажмите \"Меню\", а затем 0."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Повторите попытку"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Идет зарядка (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Заряжена."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Подключите зарядное устройство."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Нет SIM-карты."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"SIM-карта не установлена."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Идет зарядка..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Подключите зарядное устройство"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Батарея разряжена:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"осталось менее <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Расход заряда батареи"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Не удалось провести стандартный тест"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Действие FACTORY_TEST поддерживается только для пакетов, установленных в /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Перейти с этой страницы?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Нажмите \"ОК\", чтобы продолжить, или \"Отмена\", чтобы остаться на текущей странице."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Подтвердите"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"считывать историю и закладки браузера"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Разрешает приложению считывать все URL, посещенные браузером, и все его закладки."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"записывать историю и закладки браузера"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Создать контакт"\n"с номером <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"отмечено"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"не проверено"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Перечисленные приложения запрашивают разрешение на доступ к регистрационном данным аккаунта <xliff:g id="ACCOUNT">%1$s</xliff:g> из <xliff:g id="APPLICATION">%2$s</xliff:g>. Разрешить доступ? Если да, ваш ответ будет сохранен и это сообщение больше не будет выводиться."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Перечисленные приложения запрашивают разрешение на доступ к регистрационном данным <xliff:g id="TYPE">%1$s</xliff:g> аккаунта <xliff:g id="ACCOUNT">%2$s</xliff:g> из <xliff:g id="APPLICATION">%3$s</xliff:g>. Разрешить доступ? Если да, ваш ответ будет сохранен и это сообщение больше не будет выводиться."</string>
     <string name="allow" msgid="7225948811296386551">"Разрешить"</string>
     <string name="deny" msgid="2081879885755434506">"Отклонить"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Разрешение запрошено"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Специальные возможности"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновый рисунок"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Изменить фоновый рисунок"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 0f0d966..db77ee1 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Övervaka din fysiska plats"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Nätverkskommunikation"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Tillåt att program kommer åt olika nätverksfunktioner."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Dina Google-konton"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Få åtkomst till tillgängliga Google-konton."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Kontroller för maskinvara"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Direkt åtkomst till maskinvara på handenheten."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Telefonsamtal"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ange PIN-kod"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Fel PIN-kod!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Tryck på Meny och sedan på 0 om du vill låsa upp."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Försök igen"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Laddar (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Laddad."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Anslut din laddare."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Inget SIM-kort."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Inget SIM-kort i telefonen."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Laddar…"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Anslut laddaren"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteriet håller på att ta slut:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"Mindre än <xliff:g id="NUMBER">%d%%</xliff:g> återstår."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Batteriförbrukning"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Det gick fel vid fabrikstestet"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Åtgärden FACTORY_TEST stöds endast för paket som har installerats i /system/app."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Vill du lämna den här den här sidan?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Tryck på OK om du vill fortsätta eller på Avbryt om du vill vara kvar på den aktuella sidan."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Bekräfta"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"läsa webbläsarhistorik och bokmärken"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillåter att program läser alla webbadresser som webbläsaren har öppnat och alla webbläsarens bokmärken."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriva webbläsarhistorik och bokmärken"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"Skapa kontakt"\n"med <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"markerad"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"inte markerad"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Programmen begär åtkomst till inloggningsuppgifterna för kontot <xliff:g id="ACCOUNT">%1$s</xliff:g> från <xliff:g id="APPLICATION">%2$s</xliff:g>. Vill du bevilja behörighet? Om du gör det kommer vi ihåg det och du blir inte tillfrågad igen."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Programmen begär åtkomst till inloggningsuppgifterna <xliff:g id="TYPE">%1$s</xliff:g> för kontot <xliff:g id="ACCOUNT">%2$s</xliff:g> från <xliff:g id="APPLICATION">%3$s</xliff:g>. Vill du bevilja behörighet? Om du gör det kommer vi ihåg det och du blir inte tillfrågad igen."</string>
     <string name="allow" msgid="7225948811296386551">"Tillåt"</string>
     <string name="deny" msgid="2081879885755434506">"Neka"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"Begärd behörighet"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Tillgänglighet"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ändra bakgrund"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index a63a387..503ad7d 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Fiziksel konumunuzu izleyin"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Ağ iletişimi"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Uygulamaların çeşitli ağ özelliklerine erişmesine izin verir."</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"Google hesaplarınız"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"Kullanılabilir Google hesaplarına erişin."</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Donanım denetimleri"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Telefon donanımına doğrudan erişim."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Telefon çağrıları"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN kodunu gir"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Yanlış PIN kodu!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Kilidi açmak için önce Menü\'ye, sonra 0\'a basın."</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Üzgünüz, lütfen yeniden deneyin"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Şarj oluyor (<xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Şarj oldu."</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Şarj cihazınızı bağlayın."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIM kart yok."</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"Telefonda SIM kart yok."</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"Şarj oluyor…"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Lütfen şarj cihazını takın"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Pil tükeniyor:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"<xliff:g id="NUMBER">%d%%</xliff:g> adetten daha az kaldı."</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"Pil kullanımı"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Fabrika testi yapılamadı"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST işlemi yalnızca /system/app dizinine yüklenmiş paketler için desteklenir."</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Bu sayfadan ayrılıyor musunuz?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Devam etmek için Tamam\'ı, sayfada kalmak için İptal\'i tıklatın."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Onayla"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Tarayıcı geçmişini ve favorileri oku"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Uygulamaya Tarayıcının ziyaret etmiş olduğu tüm URL\'leri ve Tarayıcının tüm favorilerini okuma izni verir."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Tarayıcı geçmişini ve favorileri yaz"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"<xliff:g id="NUMBER">%s</xliff:g>"\n" ile kişi oluştur"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"seçildi"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"seçilmedi"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"Listelenen uygulamalar, <xliff:g id="APPLICATION">%2$s</xliff:g> uygulamasının <xliff:g id="ACCOUNT">%1$s</xliff:g> hesabı için giriş bilgilerine erişim izni istiyor. Bu izni vermek istiyor musunuz? İstiyorsanız yanıtınız kaydedilecek ve tekrar sorulmayacaktır."</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"Listelenen uygulamalar, <xliff:g id="APPLICATION">%3$s</xliff:g> uygulamasının <xliff:g id="ACCOUNT">%2$s</xliff:g> hesabı için <xliff:g id="TYPE">%1$s</xliff:g> girişi bilgilerine erişim izni istiyor. Bu izni vermek istiyor musunuz? İstiyorsanız yanıtınız kaydedilecek ve tekrar sorulmayacaktır."</string>
     <string name="allow" msgid="7225948811296386551">"İzin Ver"</string>
     <string name="deny" msgid="2081879885755434506">"Reddet"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"İzin İstendi"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Erişebilirlik"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Duvar Kağıdı"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Duvar kağıdını değiştir"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 2974203..474fffc 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -29,9 +29,9 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"语音信箱"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"出现连接问题或 MMI 码无效。"</string>
-    <string name="serviceEnabled" msgid="8147278346414714315">"服务已启用。"</string>
+    <string name="serviceEnabled" msgid="8147278346414714315">"已启用服务。"</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"已针对以下内容启用了服务:"</string>
-    <string name="serviceDisabled" msgid="1937553226592516411">"服务已被停用。"</string>
+    <string name="serviceDisabled" msgid="1937553226592516411">"已停用服务。"</string>
     <string name="serviceRegistered" msgid="6275019082598102493">"注册成功。"</string>
     <string name="serviceErased" msgid="1288584695297200972">"清除成功。"</string>
     <string name="passwordIncorrect" msgid="7612208839450128715">"密码不正确。"</string>
@@ -42,25 +42,25 @@
     <string name="invalidPin" msgid="3850018445187475377">"输入一个 4 至 8 位数的 PIN。"</string>
     <string name="needPuk" msgid="919668385956251611">"您的 SIM 卡被 PUK 锁定。请输入 PUK 码进行解锁。"</string>
     <string name="needPuk2" msgid="4526033371987193070">"输入 PUK2 以解锁 SIM 卡。"</string>
-    <string name="ClipMmi" msgid="6952821216480289285">"来电显示"</string>
-    <string name="ClirMmi" msgid="7784673673446833091">"外拨电话显示"</string>
+    <string name="ClipMmi" msgid="6952821216480289285">"来电者信息"</string>
+    <string name="ClirMmi" msgid="7784673673446833091">"外拨者信息"</string>
     <string name="CfMmi" msgid="5123218989141573515">"呼叫转接"</string>
     <string name="CwMmi" msgid="9129678056795016867">"呼叫等待"</string>
     <string name="BaMmi" msgid="455193067926770581">"呼叫限制"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"密码更改"</string>
     <string name="PinMmi" msgid="3113117780361190304">"PIN 码更改"</string>
     <string name="CnipMmi" msgid="3110534680557857162">"来电显示"</string>
-    <string name="CnirMmi" msgid="3062102121430548731">"来电显示已禁用"</string>
+    <string name="CnirMmi" msgid="3062102121430548731">"来电显示受限制"</string>
     <string name="ThreeWCMmi" msgid="9051047170321190368">"三方通话"</string>
     <string name="RuacMmi" msgid="7827887459138308886">"拒绝不想接听的骚扰电话"</string>
     <string name="CndMmi" msgid="3116446237081575808">"主叫号码传送"</string>
     <string name="DndMmi" msgid="1265478932418334331">"请勿打扰"</string>
-    <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"来电显示默认设置为受限制。下一个呼叫:受限制"</string>
-    <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"来电显示默认设置为受限制。下一个呼叫:不受限制"</string>
-    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"来电显示默认设置为不受限制。下一个呼叫:受限制"</string>
-    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"来电显示默认设置为不受限制。下一个呼叫:不受限制"</string>
+    <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"来电者信息在默认情况下受限制。在下一次通话中:受限制"</string>
+    <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"来电者信息在默认情况受限制。在下一次通话中:不受限制"</string>
+    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"来电者信息在默认情况下不受限制。在下一次通话中:受限制"</string>
+    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"来电者信息在默认情况下不受限制。在下一次通话中:不受限制"</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"未提供服务。"</string>
-    <string name="CLIRPermanent" msgid="5460892159398802465">"无法更改来电显示设置。"</string>
+    <string name="CLIRPermanent" msgid="5460892159398802465">"无法更改来电者信息设置。"</string>
     <string name="RestrictedChangedTitle" msgid="5592189398956187498">"访问受限情况已发生变化"</string>
     <string name="RestrictedOnData" msgid="8653794784690065540">"数据服务已禁用。"</string>
     <string name="RestrictedOnEmergency" msgid="6581163779072833665">"紧急服务已禁用。"</string>
@@ -116,7 +116,7 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"同步"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"同步"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"太多<xliff:g id="CONTENT_TYPE">%s</xliff:g>删除项。"</string>
-    <string name="low_memory" msgid="6632412458436461203">"手机存储空间已满!请删除一些文件来腾出空间。"</string>
+    <string name="low_memory" msgid="6632412458436461203">"手机内存已用完!请删除一些文件来腾出空间。"</string>
     <string name="me" msgid="6545696007631404292">"我"</string>
     <string name="power_dialog" msgid="1319919075463988638">"手机选项"</string>
     <string name="silent_mode" msgid="7167703389802618663">"静音模式"</string>
@@ -131,8 +131,8 @@
     <string name="global_action_lock" msgid="2844945191792119712">"屏幕锁定"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"关机"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"静音模式"</string>
-    <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"声音已“关闭”"</string>
-    <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"声音已“开启”"</string>
+    <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"已关闭声音"</string>
+    <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"已打开声音"</string>
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飞行模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"飞行模式已开启"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"飞行模式已关闭"</string>
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"监视您的物理位置"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"网络通信"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"允许应用程序访问各种网络功能。"</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"您的 Google 帐户"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"访问可用的 Google 帐户。"</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"硬件控制"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"直接访问手机上的硬件。"</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"手机通话"</string>
@@ -164,8 +166,8 @@
     <string name="permdesc_statusBar" msgid="1365473595331989732">"允许应用程序停用状态栏,或者添加和删除系统图标。"</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"展开/折叠状态栏"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"允许应用程序展开或折叠状态栏。"</string>
-    <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"拦截对外呼叫"</string>
-    <string name="permdesc_processOutgoingCalls" msgid="2228988201852654461">"允许应用程序处理对外呼叫和更改要拨打的号码。恶意应用程序可借此监视、重定向或阻止对外呼叫。"</string>
+    <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"拦截外拨电话"</string>
+    <string name="permdesc_processOutgoingCalls" msgid="2228988201852654461">"允许应用程序处理外拨电话和更改要拨打的号码。恶意应用程序可借此监视、重定向或阻止外拨电话。"</string>
     <string name="permlab_receiveSms" msgid="2697628268086208535">"接收短信"</string>
     <string name="permdesc_receiveSms" msgid="6298292335965966117">"允许应用程序接收和处理短信。恶意应用程序可借此监视您的信息,或者将信息删除而不向您显示。"</string>
     <string name="permlab_receiveMms" msgid="8894700916188083287">"接收彩信"</string>
@@ -178,7 +180,7 @@
     <string name="permdesc_writeSms" msgid="6299398896177548095">"允许应用程序写入手机或 SIM 卡中存储的短信。恶意应用程序可借此删除您的信息。"</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"接收 WAP"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"允许应用程序接收和处理 WAP 消息。恶意应用程序可借此监视您的消息,或者将消息删除而不向您显示。"</string>
-    <string name="permlab_getTasks" msgid="5005277531132573353">"检索所运行的应用程序"</string>
+    <string name="permlab_getTasks" msgid="5005277531132573353">"检索当前运行的应用程序"</string>
     <string name="permdesc_getTasks" msgid="7048711358713443341">"允许应用程序检索有关当前和最近运行的任务的信息。恶意应用程序可借此发现有关其他应用程序的私有信息。"</string>
     <string name="permlab_reorderTasks" msgid="5669588525059921549">"对正在运行的应用程序重新排序"</string>
     <string name="permdesc_reorderTasks" msgid="126252774270522835">"允许应用程序将任务移至前台和后台。恶意应用程序可借此强行进到前台,而不受您的控制。"</string>
@@ -204,11 +206,11 @@
     <string name="permdesc_broadcastSmsReceived" msgid="9122419277306740155">"允许应用程序广播已收到短信的通知。恶意应用程序可借此伪造收到的短信。"</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"发送 WAP 一键接收广播"</string>
     <string name="permdesc_broadcastWapPush" msgid="3955303669461378091">"允许应用程序广播收到 WAP 一键信息的通知。恶意应用程序可借此乱发彩信或暗中用恶意内容替换任意网页中的内容。"</string>
-    <string name="permlab_setProcessLimit" msgid="2451873664363662666">"限制所运行进程的数量"</string>
+    <string name="permlab_setProcessLimit" msgid="2451873664363662666">"限制运行的进程个数"</string>
     <string name="permdesc_setProcessLimit" msgid="7824786028557379539">"允许应用程序控制将运行的最大进程数。普通应用程序从不需要使用此权限。"</string>
     <string name="permlab_setAlwaysFinish" msgid="5342837862439543783">"关闭所有后台应用程序"</string>
     <string name="permdesc_setAlwaysFinish" msgid="8773936403987091620">"允许应用程序控制活动是否始终是一转至后台就完成。普通应用程序从不需要使用此权限。"</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"修改电池使用情况统计信息"</string>
+    <string name="permlab_batteryStats" msgid="7863923071360031652">"修改电池统计信息"</string>
     <string name="permdesc_batteryStats" msgid="5847319823772230560">"允许修改收集的电池使用情况统计信息。普通应用程序不能使用此权限。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"控制系统备份和还原"</string>
     <string name="permdesc_backup" msgid="4837493065154256525">"允许应用程序控制系统的备份和还原机制。不适用于普通应用程序。"</string>
@@ -221,7 +223,7 @@
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"修改全局动画速度"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"允许应用程序随时更改全局动画速度(加快或放慢动画)。"</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"管理应用程序令牌"</string>
-    <string name="permdesc_manageAppTokens" msgid="977127907524195988">"允许应用程序创建和管理自己的令牌,从而绕开正常的 Z 排序方式。普通应用程序从不需要使用此权限。"</string>
+    <string name="permdesc_manageAppTokens" msgid="977127907524195988">"允许应用程序创建和管理自己的令牌,从而绕开正常的 Z 方向排序。普通应用程序从不需要使用此权限。"</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"按键和控制按钮"</string>
     <string name="permdesc_injectEvents" msgid="3946098050410874715">"允许应用程序将其自己的输入活动(按键等)提供给其他应用程序。恶意应用程序可借此掌控手机。"</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"记录您输入的内容和采取的操作"</string>
@@ -230,7 +232,7 @@
     <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"允许手机用户绑定至输入法的顶级界面。普通应用程序从不需要使用此权限。"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"绑定到壁纸"</string>
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"允许手机用户绑定到壁纸的顶级界面。应该从不需要将此权限授予普通应用程序。"</string>
-    <string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕浏览模式"</string>
+    <string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕显示方向"</string>
     <string name="permdesc_setOrientation" msgid="6335814461615851863">"允许应用程序随时更改屏幕的旋转方向。普通应用程序从不需要使用此权限。"</string>
     <string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"向应用程序发送 Linux 信号"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"允许应用程序请求将提供的信号发送给所有持续的进程。"</string>
@@ -247,7 +249,7 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"直接安装应用程序"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"允许应用程序安装新的或更新的 Android 包。恶意应用程序可借此添加具有极大权限的新应用程序。"</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"删除所有应用程序缓存数据"</string>
-    <string name="permdesc_clearAppCache" msgid="7740465694193671402">"允许应用程序通过删除应用程序缓存目录中的文件释放手机存储空间。对系统进程的访问通常受到严格限制。"</string>
+    <string name="permdesc_clearAppCache" msgid="7740465694193671402">"允许应用程序通过删除应用程序缓存目录中的文件释放手机内存。通常严格限制访问系统进程。"</string>
     <string name="permlab_readLogs" msgid="4811921703882532070">"读取系统日志文件"</string>
     <string name="permdesc_readLogs" msgid="2257937955580475902">"允许应用程序读取系统的各日志文件。这样应用程序可以发现有关您操作手机的一般信息,但这些信息不应包含任何个人信息或私有信息。"</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"读取/写入诊断所拥有的资源"</string>
@@ -264,7 +266,7 @@
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"允许应用程序修改 Google 服务地图。普通应用程序不能使用此权限。"</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"开机时自动启动"</string>
     <string name="permdesc_receiveBootCompleted" msgid="698336728415008796">"允许应用程序在系统完成启动后即自行启动。这样会延长手机的启动时间,而且如果应用程序一直运行,会降低手机的整体速度。"</string>
-    <string name="permlab_broadcastSticky" msgid="7919126372606881614">"发送顽固广播"</string>
+    <string name="permlab_broadcastSticky" msgid="7919126372606881614">"发送置顶广播"</string>
     <string name="permdesc_broadcastSticky" msgid="1920045289234052219">"允许应用程序发送顽固广播,这些广播在结束后仍会保留。恶意应用程序可能会借此使手机耗用太多内存,从而降低其速度或稳定性。"</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"读取联系人数据"</string>
     <string name="permdesc_readContacts" msgid="3371591512896545975">"允许应用程序读取您手机上存储的所有联系人(地址)数据。恶意应用程序可借此将您的数据发送给其他人。"</string>
@@ -278,11 +280,11 @@
     <string name="permdesc_readCalendar" msgid="5533029139652095734">"允许应用程序读取您手机上存储的所有日历活动。恶意应用程序可借此将您的日历活动发送给其他人。"</string>
     <string name="permlab_writeCalendar" msgid="377926474603567214">"写入日历数据"</string>
     <string name="permdesc_writeCalendar" msgid="8674240662630003173">"允许应用程序修改您手机上存储的日历活动。恶意应用程序可借此清除或修改您的日历数据。"</string>
-    <string name="permlab_accessMockLocation" msgid="8688334974036823330">"用于测试的模拟位置源"</string>
+    <string name="permlab_accessMockLocation" msgid="8688334974036823330">"禁止使用位置来源进行测试"</string>
     <string name="permdesc_accessMockLocation" msgid="7648286063459727252">"创建用于测试的模拟位置源。恶意应用程序可借此替代真正的位置源(如 GPS 或网络提供商)返回的位置和/或状态。"</string>
-    <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"接收额外的位置提供者命令"</string>
+    <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"访问更多位置提供者的命令"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="1948144701382451721">"访问额外的位置提供程序命令。恶意应用程序可借此干扰 GPS 或其他位置源的运作。"</string>
-    <string name="permlab_installLocationProvider" msgid="6578101199825193873">"安装地点信息提供程序的权限"</string>
+    <string name="permlab_installLocationProvider" msgid="6578101199825193873">"安装位置信息提供程序"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"创建用于测试的模拟地点信息源。恶意应用程序可借此覆盖真正的地点信息源(如 GPS 或网络提供商)返回的地点和/或状态,或者监视您的地点并向外部信息源报告。"</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"精准位置 (GPS)"</string>
     <string name="permdesc_accessFineLocation" msgid="7411213317434337331">"访问精准的位置源,例如手机上的全球定位系统(如果适用)。恶意应用程序可能借此确定您所处的位置,并消耗额外的电池电量。"</string>
@@ -313,9 +315,9 @@
     <string name="permlab_hardware_test" msgid="4148290860400659146">"测试硬件"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"允许应用程序控制各种用于硬件测试的外围设备。"</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"直接拨打电话号码"</string>
-    <string name="permdesc_callPhone" msgid="3369867353692722456">"允许应用程序在没有您干预的情况下呼叫电话号码。恶意应用程序可借此在您的话费单上产生意外通话费。请注意,此权限不允许应用程序呼叫紧急电话号码。"</string>
+    <string name="permdesc_callPhone" msgid="3369867353692722456">"允许应用程序在无人操作的情况下拨打电话。恶意应用程序可借此在您的话费单上产生意外通话费。请注意,此权限不允许应用程序拨打紧急电话。"</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"直接呼叫任何电话号码"</string>
-    <string name="permdesc_callPrivileged" msgid="244405067160028452">"允许应用程序在没有您干预的情况下呼叫任何电话号码(包括紧急电话号码)。恶意应用程序可借此对紧急服务拨打骚扰电话和非法电话。"</string>
+    <string name="permdesc_callPrivileged" msgid="244405067160028452">"允许应用程序在无人操作的情况下拨打任何电话(包括紧急电话)。恶意应用程序可借此向紧急服务拨打骚扰电话和非法电话。"</string>
     <string name="permlab_performCdmaProvisioning" msgid="5604848095315421425">"直接启动 CDMA 电话设置"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"允许应用程序启动 CDMA 服务。恶意应用程序可能会无端启动 CDMA 服务"</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"控制位置更新通知"</string>
@@ -354,7 +356,7 @@
     <string name="permdesc_useCredentials" msgid="7416570544619546974">"允许应用程序请求身份验证标记。"</string>
     <string name="permlab_accessNetworkState" msgid="6865575199464405769">"查看网络状态"</string>
     <string name="permdesc_accessNetworkState" msgid="558721128707712766">"允许应用程序查看所有网络的状态。"</string>
-    <string name="permlab_createNetworkSockets" msgid="9121633680349549585">"互联网完全访问"</string>
+    <string name="permlab_createNetworkSockets" msgid="9121633680349549585">"完全访问互联网"</string>
     <string name="permdesc_createNetworkSockets" msgid="4593339106921772192">"允许应用程序创建网络套接字。"</string>
     <string name="permlab_writeApnSettings" msgid="7823599210086622545">"写入接入点名称设置"</string>
     <string name="permdesc_writeApnSettings" msgid="7443433457842966680">"允许应用程序修改 APN 设置,例如任何 APN 的代理和端口。"</string>
@@ -407,10 +409,10 @@
     <item msgid="2374913952870110618">"自定义邮箱"</item>
   </string-array>
   <string-array name="postalAddressTypes">
-    <item msgid="6880257626740047286">"住宅地址"</item>
-    <item msgid="5629153956045109251">"单位地址"</item>
-    <item msgid="4966604264500343469">"其他地址"</item>
-    <item msgid="4932682847595299369">"自定义地址"</item>
+    <item msgid="6880257626740047286">"住宅"</item>
+    <item msgid="5629153956045109251">"单位"</item>
+    <item msgid="4966604264500343469">"其他"</item>
+    <item msgid="4932682847595299369">"自定义"</item>
   </string-array>
   <string-array name="imAddressTypes">
     <item msgid="1738585194601476694">"住宅聊天工具"</item>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"输入 PIN 码"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"PIN 码不正确!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"要解锁,请先按 MENU 再按 0。"</string>
@@ -446,15 +552,17 @@
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"正确!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"很抱歉,请重试"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"正在充电 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"电已充满。"</string>
+    <string name="lockscreen_charged" msgid="4938930459620989972">"已充满。"</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"连接您的充电器。"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"没有 SIM 卡。"</string>
-    <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"手机中无 SIM 卡。"</string>
-    <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"请插入 SIM 卡。"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"没有 SIM 卡"</string>
+    <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"手机中无 SIM 卡"</string>
+    <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"请插入 SIM 卡"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"网络已锁定"</string>
-    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM 卡被 PUK 锁定。"</string>
+    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM 卡被 PUK 锁定"</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="635967534992394321">"请参阅《用户指南》或联系客服人员。"</string>
-    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM 卡被锁定。"</string>
+    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM 卡被锁定"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"正在解锁 SIM 卡..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。"\n\n"请在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒后重试。"</string>
     <string name="lockscreen_failed_attempts_almost_glogin" msgid="3351013842320127827">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统会要求您使用自己的 Google 登录信息解锁手机。"\n\n"请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"正在充电..."</string>
     <string name="battery_low_title" msgid="7923774589611311406">"请连接充电器"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"电量在减少:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"剩余电量不足 <xliff:g id="NUMBER">%d%%</xliff:g>。"</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"电量使用情况"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"出厂测试失败"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"只有 /system/app 中安装的包支持 FACTORY_TEST 操作。"</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"是否从该页面导航至它处?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"选择“确定”继续,或选择“取消”留在当前页面。"</string>
     <string name="save_password_label" msgid="6860261758665825069">"确认"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"读取浏览器的历史记录和书签"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允许应用程序读取用浏览器访问过的所有网址,以及浏览器的所有书签。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"写入浏览器的历史记录和书签"</string>
@@ -614,16 +725,16 @@
     <string name="addToDictionary" msgid="8793624991686948709">"将“<xliff:g id="WORD">%s</xliff:g>”添加到词典"</string>
     <string name="editTextMenuTitle" msgid="1672989176958581452">"编辑文字"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"空间不足"</string>
-    <string name="low_internal_storage_view_text" msgid="635106544616378836">"手机存储空间正在减少。"</string>
+    <string name="low_internal_storage_view_text" msgid="635106544616378836">"手机内存空间正在减少。"</string>
     <string name="ok" msgid="5970060430562524910">"确定"</string>
     <string name="cancel" msgid="6442560571259935130">"取消"</string>
     <string name="yes" msgid="5362982303337969312">"确定"</string>
     <string name="no" msgid="5141531044935541497">"取消"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"注意事项"</string>
-    <string name="capital_on" msgid="1544682755514494298">"开启"</string>
+    <string name="capital_on" msgid="1544682755514494298">"打开"</string>
     <string name="capital_off" msgid="6815870386972805832">"关闭"</string>
-    <string name="whichApplication" msgid="4533185947064773386">"使用以下内容完成操作"</string>
-    <string name="alwaysUse" msgid="4583018368000610438">"默认用于执行此操作。"</string>
+    <string name="whichApplication" msgid="4533185947064773386">"使用以下方式发送"</string>
+    <string name="alwaysUse" msgid="4583018368000610438">"默认使用此方式发送。"</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"清除“主屏幕设置”&gt;“应用程序”&gt;“管理应用程序”中的默认设置。"</string>
     <string name="chooseActivity" msgid="1009246475582238425">"选择一项操作"</string>
     <string name="noApplications" msgid="1691104391758345586">"没有应用程序可执行此操作。"</string>
@@ -680,7 +791,7 @@
     <string name="usb_storage_button_unmount" msgid="6092146330053864766">"不安装"</string>
     <string name="usb_storage_error_message" msgid="2534784751603345363">"使用 SD 卡进行 USB 存储时出现问题。"</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 已连接"</string>
-    <string name="usb_storage_notification_message" msgid="7380082404288219341">"选择以将文件复制到计算机/从计算机复制文件。"</string>
+    <string name="usb_storage_notification_message" msgid="7380082404288219341">"选择将文件复制到计算机/从计算机复制到存储设备。"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"关闭 USB 存储设备"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"选中以关闭 USB 存储设备。"</string>
     <string name="usb_storage_stop_title" msgid="6014127947456185321">"关闭 USB 存储设备"</string>
@@ -691,7 +802,7 @@
     <string name="extmedia_format_title" msgid="8663247929551095854">"格式化 SD 卡"</string>
     <string name="extmedia_format_message" msgid="3621369962433523619">"您确定要格式化 SD 卡?卡上的所有数据都会丢失。"</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"格式化"</string>
-    <string name="adb_active_notification_title" msgid="6729044778949189918">"已连接 USB 调试接口"</string>
+    <string name="adb_active_notification_title" msgid="6729044778949189918">"已连接 USB 调试"</string>
     <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
     <skip />
     <!-- no translation found for select_input_method (6865512749462072765) -->
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"创建电话号码为"\n"<xliff:g id="NUMBER">%s</xliff:g> 的联系人"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"已选中"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"未选中"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"所列应用程序正在请求相应的权限,以便从<xliff:g id="APPLICATION">%2$s</xliff:g>访问 <xliff:g id="ACCOUNT">%1$s</xliff:g> 帐户的登录凭据。是否要授予这种权限?如果授予,系统会记住您所做的选择,且不再提示。"</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"所列应用程序正在请求相应的权限,以便从<xliff:g id="APPLICATION">%3$s</xliff:g>访问 <xliff:g id="ACCOUNT">%2$s</xliff:g> 帐户的<xliff:g id="TYPE">%1$s</xliff:g>登录凭据。是否要授予这种权限?如果授予,系统会记住您所做的选择,且不再提示。"</string>
     <string name="allow" msgid="7225948811296386551">"允许"</string>
     <string name="deny" msgid="2081879885755434506">"拒绝"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"已请求权限"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"辅助功能"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁纸"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"更改壁纸"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 8f9f310..3542536 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -148,8 +148,10 @@
     <string name="permgroupdesc_location" msgid="2430258821648348660">"監視實際位置"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"網路通訊"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"允許應用程式存取多項網路功能。"</string>
-    <string name="permgrouplab_accounts" msgid="7140261692496314430">"您的 Google 帳戶"</string>
-    <string name="permgroupdesc_accounts" msgid="6735915929704895193">"存取可用 Google 帳戶。"</string>
+    <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
+    <skip />
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"硬體控制"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"在免持設備上直接存取硬體。"</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"撥打電話"</string>
@@ -433,6 +435,110 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
+    <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
+    <skip />
+    <!-- no translation found for phoneTypeHome (2570923463033985887) -->
+    <skip />
+    <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
+    <skip />
+    <!-- no translation found for phoneTypeWork (8863939667059911633) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
+    <skip />
+    <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
+    <skip />
+    <!-- no translation found for phoneTypePager (7582359955394921732) -->
+    <skip />
+    <!-- no translation found for phoneTypeOther (1544425847868765990) -->
+    <skip />
+    <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
+    <skip />
+    <!-- no translation found for phoneTypeCar (8738360689616716982) -->
+    <skip />
+    <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
+    <skip />
+    <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
+    <skip />
+    <!-- no translation found for phoneTypeMain (6766137010628326916) -->
+    <skip />
+    <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
+    <skip />
+    <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
+    <skip />
+    <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
+    <skip />
+    <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
+    <skip />
+    <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
+    <skip />
+    <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
+    <skip />
+    <!-- no translation found for phoneTypeMms (7254492275502768992) -->
+    <skip />
+    <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
+    <skip />
+    <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
+    <skip />
+    <!-- no translation found for eventTypeOther (5834288791948564594) -->
+    <skip />
+    <!-- no translation found for emailTypeCustom (8525960257804213846) -->
+    <skip />
+    <!-- no translation found for emailTypeHome (449227236140433919) -->
+    <skip />
+    <!-- no translation found for emailTypeWork (3548058059601149973) -->
+    <skip />
+    <!-- no translation found for emailTypeOther (2923008695272639549) -->
+    <skip />
+    <!-- no translation found for emailTypeMobile (119919005321166205) -->
+    <skip />
+    <!-- no translation found for postalTypeCustom (8903206903060479902) -->
+    <skip />
+    <!-- no translation found for postalTypeHome (8165756977184483097) -->
+    <skip />
+    <!-- no translation found for postalTypeWork (5268172772387694495) -->
+    <skip />
+    <!-- no translation found for postalTypeOther (2726111966623584341) -->
+    <skip />
+    <!-- no translation found for imTypeCustom (2074028755527826046) -->
+    <skip />
+    <!-- no translation found for imTypeHome (6241181032954263892) -->
+    <skip />
+    <!-- no translation found for imTypeWork (1371489290242433090) -->
+    <skip />
+    <!-- no translation found for imTypeOther (5377007495735915478) -->
+    <skip />
+    <!-- no translation found for imProtocolCustom (6919453836618749992) -->
+    <skip />
+    <!-- no translation found for imProtocolAim (7050360612368383417) -->
+    <skip />
+    <!-- no translation found for imProtocolMsn (144556545420769442) -->
+    <skip />
+    <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
+    <skip />
+    <!-- no translation found for imProtocolSkype (9019296744622832951) -->
+    <skip />
+    <!-- no translation found for imProtocolQq (8887484379494111884) -->
+    <skip />
+    <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
+    <skip />
+    <!-- no translation found for imProtocolIcq (1574870433606517315) -->
+    <skip />
+    <!-- no translation found for imProtocolJabber (2279917630875771722) -->
+    <skip />
+    <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
+    <skip />
+    <!-- no translation found for orgTypeWork (29268870505363872) -->
+    <skip />
+    <!-- no translation found for orgTypeOther (3951781131570124082) -->
+    <skip />
+    <!-- no translation found for orgTypeCustom (225523415372088322) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution (5112589886094402795) -->
+    <skip />
+    <!-- no translation found for contact_status_update_attribution_with_date (5945386376369979909) -->
+    <skip />
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"輸入 PIN 碼"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"PIN 碼錯誤!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"如要解鎖,請按 Menu 鍵,然後按 0。"</string>
@@ -447,6 +553,8 @@
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"很抱歉,請再試一次"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"正在充電 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"充電完成。"</string>
+    <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"請連接充電器。"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"沒有 SIM  卡。"</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"手機未插入 SIM 卡。"</string>
@@ -478,7 +586,8 @@
     <string name="battery_status_charging" msgid="756617993998772213">"充電中"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"請連接充電器"</string>
     <string name="battery_low_subtitle" msgid="7388781709819722764">"電池電量即將不足:"</string>
-    <string name="battery_low_percent_format" msgid="6564958083485073855">"電池電量不到 <xliff:g id="NUMBER">%d%%</xliff:g>。"</string>
+    <!-- no translation found for battery_low_percent_format (696154104579022959) -->
+    <skip />
     <string name="battery_low_why" msgid="7279169609518386372">"電池使用狀況"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"出廠測試失敗"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"只有安裝在 /system/app 裡的程式才能支援 FACTORY_TEST 操作。"</string>
@@ -488,6 +597,8 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"離開此頁?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n" 選取 [確定] 離開此頁;或 [取消] 留在此頁。"</string>
     <string name="save_password_label" msgid="6860261758665825069">"確認"</string>
+    <!-- no translation found for double_tap_toast (1068216937244567247) -->
+    <skip />
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"讀取瀏覽器的記錄與書籤"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允許應用程式讀取瀏覽器曾經造訪過的所有網址,以及瀏覽器的所有書籤。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"寫入瀏覽器的記錄與書籤"</string>
@@ -726,8 +837,6 @@
     <string name="create_contact_using" msgid="4947405226788104538">"建立手機號碼為 <xliff:g id="NUMBER">%s</xliff:g>"\n"的聯絡人"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"已勾選"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"未勾選"</string>
-    <string name="grant_credentials_permission_message_desc" msgid="6883276587034335667">"這些應用程式要求存取「<xliff:g id="APPLICATION">%2$s</xliff:g>」的 <xliff:g id="ACCOUNT">%1$s</xliff:g> 帳戶登入認證的權限,您要授予此權限嗎?如果確定授予,系統會記住您的選擇,不會再次詢問您。"</string>
-    <string name="grant_credentials_permission_message_with_authtokenlabel_desc" msgid="3159007601893584687">"這些應用程式要求存取「<xliff:g id="APPLICATION">%3$s</xliff:g>」的 <xliff:g id="ACCOUNT">%2$s</xliff:g> 帳戶「<xliff:g id="TYPE">%1$s</xliff:g>」登入認證的權限,您要授予此權限嗎?如果確定授予,系統會記住您的選擇,不會再次詢問您。"</string>
     <string name="allow" msgid="7225948811296386551">"允許"</string>
     <string name="deny" msgid="2081879885755434506">"拒絕"</string>
     <string name="permission_request_notification_title" msgid="5390555465778213840">"已要求權限"</string>
@@ -738,4 +847,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"協助工具"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
+    <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
+    <skip />
+    <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
+    <skip />
+    <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 5d3069b..a506c9a 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -78,6 +78,7 @@
     <!-- For security permissions -->
     <color name="perms_dangerous_grp_color">#dd6826</color>
     <color name="perms_dangerous_perm_color">#dd6826</color>
+    <color name="shadow">#cc222222</color>
 
     <!-- For search-related UIs -->
     <color name="search_url_text_normal">#7fa87f</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c87a11c..274ec2b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -40,6 +40,10 @@
     <!-- The duration (in milliseconds) of a long animation. -->
     <integer name="config_longAnimTime">400</integer>
 
+    <!-- The duration (in milliseconds) that the radio will scan for a signal
+         when there's no network connection. If the scan doesn't timeout, use zero -->
+    <integer name="config_radioScanningTimeout">0</integer>
+
     <!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION.
          Please don't copy them, copy anything else. -->
          
@@ -67,7 +71,11 @@
          the slider can be opened (for example, in a pocket or purse). -->
     <bool name="config_bypass_keyguard_if_slider_open">true</bool>
     
-    <!-- Flag indicating whether the device supports automatic brightness mode. -->
+    <!-- Flag indicating whether the device supports automatic brightness mode in hardware. -->
+    <bool name="config_hardware_automatic_brightness_available">false</bool>
+
+    <!-- Flag indicating whether the we should enable the automatic brightness in Settings.
+         Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
     
     <!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION -->
@@ -160,4 +168,38 @@
 
     <!-- Control whether status bar should distinguish HSPA data icon form UMTS data icon on devices -->
     <bool name="config_hspa_data_distinguishable">false</bool>
+
+    <!-- Array of light sensor LUX values to define our levels for auto backlight brightness support.
+         The N entries of this array define N + 1 zones as follows:
+
+         Zone 0:        0 <= LUX < array[0]
+         Zone 1:        array[0] <= LUX < array[1]
+         ...
+         Zone N:        array[N - 1] <= LUX < array[N]
+         Zone N + 1:    array[N] <= LUX < infinity
+
+         Must be overridden in platform specific overlays -->
+    <integer-array name="config_autoBrightnessLevels">
+    </integer-array>
+
+    <!-- Array of output values for LCD backlight corresponding to the LUX values
+         in the config_autoBrightnessLevels array.  This array should have size one greater
+         than the size of the config_autoBrightnessLevels array.
+         This must be overridden in platform specific overlays -->
+    <integer-array name="config_autoBrightnessLcdBacklightValues">
+    </integer-array>
+
+    <!-- Array of output values for button backlight corresponding to the LUX values
+         in the config_autoBrightnessLevels array.  This array should have size one greater
+         than the size of the config_autoBrightnessLevels array.
+         This must be overridden in platform specific overlays -->
+    <integer-array name="config_autoBrightnessButtonBacklightValues">
+    </integer-array>
+
+    <!-- Array of output values for keyboard backlight corresponding to the LUX values
+         in the config_autoBrightnessLevels array.  This array should have size one greater
+         than the size of the config_autoBrightnessLevels array.
+         This must be overridden in platform specific overlays -->
+    <integer-array name="config_autoBrightnessKeyboardBacklightValues">
+    </integer-array>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index de30fe7..83a6dc5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2067,16 +2067,9 @@
     <!-- 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 <xliff:g id="account" example="foo@gmail.com">%1$s</xliff:g> from
-    <xliff:g id="application" example="Google Apps">%2$s</xliff:g>. Do you wish to grant this permission? If so, 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 <xliff:g id="type" example="Contacts">%1$s</xliff:g> login credentials for account <xliff:g id="account" example="foo@gmail.com">%2$s</xliff:g> from
-    <xliff:g id="application" example="Google Apps">%3$s</xliff:g>. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
-    again.</string>
-
+    <string name="grant_credentials_permission_message_header">The following one or more applications request permission to access your account, now and in the future.</string>
+    <string name="grant_credentials_permission_message_footer">Do you want to allow this request?</string>
+    <string name="grant_permissions_header_text">Access Request</string>
     <string name="allow">Allow</string>
     <string name="deny">Deny</string>
     <string name="permission_request_notification_title">Permission Requested</string>
@@ -2100,4 +2093,6 @@
     <string name="l2tp_vpn_description">Layer 2 Tunneling Protocol</string>
     <string name="l2tp_ipsec_psk_vpn_description">Pre-shared key based L2TP/IPSec VPN</string>
     <string name="l2tp_ipsec_crt_vpn_description">Certificate based L2TP/IPSec VPN</string>
+    <!-- Label for button in a WebView that will open a chooser to choose a file to upload -->
+    <string name="upload_file">Choose file</string>
 </resources>
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index 710b71e..ce623e8 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -29,10 +29,12 @@
   <item name="dsp.audio">0.1</item>
   <item name="dsp.video">0.1</item>
   <item name="radio.active">1</item>
+  <!-- The current consumed by the radio when it is scanning for a signal -->
+  <item name="radio.scanning">0.5</item>
   <item name="gps.on">1</item>
   <!-- Current consumed by the radio at different signal strengths, when paging -->
   <array name="radio.on"> <!-- Strength 0 to BINS-1 -->
-      <value>1</value>
+      <value>0.2</value>
       <value>0.1</value>
   </array>
   <!-- Different CPU speeds as reported in
diff --git a/data/sounds/AudioPackage3.mk b/data/sounds/AudioPackage3.mk
new file mode 100644
index 0000000..f2f6212
--- /dev/null
+++ b/data/sounds/AudioPackage3.mk
@@ -0,0 +1,92 @@
+#
+# Audio Package 2
+# 
+# Include this file in a product makefile to include these audio files
+#
+# This is a larger package of sounds than the 1.0 release for devices
+# that have larger internal flash.
+# 
+
+LOCAL_PATH:= frameworks/base/data/sounds
+
+PRODUCT_COPY_FILES += \
+	$(LOCAL_PATH)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \
+	$(LOCAL_PATH)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \
+	$(LOCAL_PATH)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \
+	$(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
+	$(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
+	$(LOCAL_PATH)/Alarm_Beep_02.ogg:system/media/audio/alarms/Alarm_Beep_02.ogg \
+	$(LOCAL_PATH)/Alarm_Classic.ogg:system/media/audio/alarms/Alarm_Classic.ogg \
+	$(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \
+	$(LOCAL_PATH)/Alarm_Rooster_02.ogg:system/media/audio/alarms/Alarm_Rooster_02.ogg \
+	$(LOCAL_PATH)/Ring_Classic_02.ogg:system/media/audio/ringtones/Ring_Classic_02.ogg \
+	$(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)/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 \
+	$(LOCAL_PATH)/newwavelabs/CurveBall.ogg:system/media/audio/ringtones/CurveBall.ogg \
+	$(LOCAL_PATH)/newwavelabs/EtherShake.ogg:system/media/audio/ringtones/EtherShake.ogg \
+	$(LOCAL_PATH)/newwavelabs/Growl.ogg:system/media/audio/ringtones/Growl.ogg \
+	$(LOCAL_PATH)/newwavelabs/LoopyLounge.ogg:system/media/audio/ringtones/LoopyLounge.ogg \
+	$(LOCAL_PATH)/newwavelabs/LoveFlute.ogg:system/media/audio/ringtones/LoveFlute.ogg \
+	$(LOCAL_PATH)/newwavelabs/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \
+	$(LOCAL_PATH)/newwavelabs/MildlyAlarming.ogg:system/media/audio/ringtones/MildlyAlarming.ogg \
+	$(LOCAL_PATH)/newwavelabs/NewPlayer.ogg:system/media/audio/ringtones/NewPlayer.ogg \
+	$(LOCAL_PATH)/newwavelabs/Noises1.ogg:system/media/audio/ringtones/Noises1.ogg \
+	$(LOCAL_PATH)/newwavelabs/Noises2.ogg:system/media/audio/ringtones/Noises2.ogg \
+	$(LOCAL_PATH)/newwavelabs/Noises3.ogg:system/media/audio/ringtones/Noises3.ogg \
+	$(LOCAL_PATH)/newwavelabs/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \
+	$(LOCAL_PATH)/newwavelabs/Terminated.ogg:system/media/audio/ringtones/Terminated.ogg \
+	$(LOCAL_PATH)/newwavelabs/TwirlAway.ogg:system/media/audio/ringtones/TwirlAway.ogg \
+	$(LOCAL_PATH)/newwavelabs/World.ogg:system/media/audio/ringtones/World.ogg \
+	$(LOCAL_PATH)/newwavelabs/CaffeineSnake.ogg:system/media/audio/notifications/CaffeineSnake.ogg \
+	$(LOCAL_PATH)/newwavelabs/DearDeer.ogg:system/media/audio/notifications/DearDeer.ogg \
+	$(LOCAL_PATH)/newwavelabs/DontPanic.ogg:system/media/audio/notifications/DontPanic.ogg \
+	$(LOCAL_PATH)/newwavelabs/Highwire.ogg:system/media/audio/notifications/Highwire.ogg \
+	$(LOCAL_PATH)/newwavelabs/KzurbSonar.ogg:system/media/audio/notifications/KzurbSonar.ogg \
+	$(LOCAL_PATH)/newwavelabs/OnTheHunt.ogg:system/media/audio/notifications/OnTheHunt.ogg \
+	$(LOCAL_PATH)/newwavelabs/Voila.ogg:system/media/audio/notifications/Voila.ogg \
+	$(LOCAL_PATH)/notifications/Beat_Box_Android.ogg:system/media/audio/notifications/Beat_Box_Android.ogg \
+	$(LOCAL_PATH)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \
+	$(LOCAL_PATH)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \
+	$(LOCAL_PATH)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \
+	$(LOCAL_PATH)/effects/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+	$(LOCAL_PATH)/effects/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
+	$(LOCAL_PATH)/effects/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+	$(LOCAL_PATH)/effects/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
+	$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
+	$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/newwavelabs/Big_Easy.ogg:system/media/audio/ringtones/Big_Easy.ogg \
+	$(LOCAL_PATH)/newwavelabs/Bollywood.ogg:system/media/audio/ringtones/Bollywood.ogg \
+	$(LOCAL_PATH)/newwavelabs/Cairo.ogg:system/media/audio/ringtones/Cairo.ogg \
+	$(LOCAL_PATH)/newwavelabs/Calypso_Steel.ogg:system/media/audio/ringtones/Calypso_Steel.ogg \
+	$(LOCAL_PATH)/newwavelabs/Champagne_Edition.ogg:system/media/audio/ringtones/Champagne_Edition.ogg \
+	$(LOCAL_PATH)/newwavelabs/Club_Cubano.ogg:system/media/audio/ringtones/Club_Cubano.ogg \
+	$(LOCAL_PATH)/newwavelabs/Eastern_Sky.ogg:system/media/audio/ringtones/Eastern_Sky.ogg \
+	$(LOCAL_PATH)/newwavelabs/Funk_Yall.ogg:system/media/audio/ringtones/Funk_Yall.ogg \
+	$(LOCAL_PATH)/newwavelabs/Savannah.ogg:system/media/audio/ringtones/Savannah.ogg \
+	$(LOCAL_PATH)/newwavelabs/Gimme_Mo_Town.ogg:system/media/audio/ringtones/Gimme_Mo_Town.ogg \
+	$(LOCAL_PATH)/newwavelabs/Glacial_Groove.ogg:system/media/audio/ringtones/Glacial_Groove.ogg \
+	$(LOCAL_PATH)/newwavelabs/Seville.ogg:system/media/audio/ringtones/Seville.ogg \
+	$(LOCAL_PATH)/newwavelabs/No_Limits.ogg:system/media/audio/ringtones/No_Limits.ogg \
+	$(LOCAL_PATH)/newwavelabs/Paradise_Island.ogg:system/media/audio/ringtones/Paradise_Island.ogg \
+	$(LOCAL_PATH)/newwavelabs/Road_Trip.ogg:system/media/audio/ringtones/Road_Trip.ogg \
+	$(LOCAL_PATH)/newwavelabs/Shes_All_That.ogg:system/media/audio/ringtones/Shes_All_That.ogg \
+	$(LOCAL_PATH)/newwavelabs/Steppin_Out.ogg:system/media/audio/ringtones/Steppin_Out.ogg \
+	$(LOCAL_PATH)/newwavelabs/Third_Eye.ogg:system/media/audio/ringtones/Third_Eye.ogg \
+	$(LOCAL_PATH)/newwavelabs/Thunderfoot.ogg:system/media/audio/ringtones/Thunderfoot.ogg \
+	$(LOCAL_PATH)/newwavelabs/HalfwayHome.ogg:system/media/audio/ringtones/HalfwayHome.ogg \
+	$(LOCAL_PATH)/newwavelabs/CrayonRock.ogg:system/media/audio/ringtones/CrayonRock.ogg \
+	$(LOCAL_PATH)/newwavelabs/DancinFool.ogg:system/media/audio/ringtones/DancinFool.ogg \
+	$(LOCAL_PATH)/newwavelabs/BussaMove.ogg:system/media/audio/ringtones/BussaMove.ogg \
+	$(LOCAL_PATH)/newwavelabs/DonMessWivIt.ogg:system/media/audio/ringtones/DonMessWivIt.ogg \
+	$(LOCAL_PATH)/newwavelabs/SilkyWay.ogg:system/media/audio/ringtones/SilkyWay.ogg \
+	$(LOCAL_PATH)/newwavelabs/Playa.ogg:system/media/audio/ringtones/Playa.ogg \
+	$(LOCAL_PATH)/notifications/moonbeam.ogg:system/media/audio/notifications/moonbeam.ogg \
+	$(LOCAL_PATH)/notifications/pixiedust.ogg:system/media/audio/notifications/pixiedust.ogg \
+	$(LOCAL_PATH)/notifications/pizzicato.ogg:system/media/audio/notifications/pizzicato.ogg \
+	$(LOCAL_PATH)/notifications/tweeters.ogg:system/media/audio/notifications/tweeters.ogg
+
diff --git a/data/sounds/newwavelabs/BussaMove.ogg b/data/sounds/newwavelabs/BussaMove.ogg
new file mode 100644
index 0000000..7c9f7b5
--- /dev/null
+++ b/data/sounds/newwavelabs/BussaMove.ogg
Binary files differ
diff --git a/data/sounds/newwavelabs/BussaMove.wav b/data/sounds/newwavelabs/BussaMove.wav
new file mode 100644
index 0000000..a82d62b
--- /dev/null
+++ b/data/sounds/newwavelabs/BussaMove.wav
Binary files differ
diff --git a/data/sounds/newwavelabs/CrayonRock.ogg b/data/sounds/newwavelabs/CrayonRock.ogg
new file mode 100644
index 0000000..6827aa5
--- /dev/null
+++ b/data/sounds/newwavelabs/CrayonRock.ogg
Binary files differ
diff --git a/data/sounds/newwavelabs/CrayonRock.wav b/data/sounds/newwavelabs/CrayonRock.wav
new file mode 100644
index 0000000..ce42f38
--- /dev/null
+++ b/data/sounds/newwavelabs/CrayonRock.wav
Binary files differ
diff --git a/data/sounds/newwavelabs/DancinFool.ogg b/data/sounds/newwavelabs/DancinFool.ogg
new file mode 100644
index 0000000..39e3b8a
--- /dev/null
+++ b/data/sounds/newwavelabs/DancinFool.ogg
Binary files differ
diff --git a/data/sounds/newwavelabs/DancinFool.wav b/data/sounds/newwavelabs/DancinFool.wav
new file mode 100644
index 0000000..f5ef13f
--- /dev/null
+++ b/data/sounds/newwavelabs/DancinFool.wav
Binary files differ
diff --git a/data/sounds/newwavelabs/DonMessWivIt.ogg b/data/sounds/newwavelabs/DonMessWivIt.ogg
new file mode 100644
index 0000000..5b14ba5
--- /dev/null
+++ b/data/sounds/newwavelabs/DonMessWivIt.ogg
Binary files differ
diff --git a/data/sounds/newwavelabs/DonMessWivIt.wav b/data/sounds/newwavelabs/DonMessWivIt.wav
new file mode 100644
index 0000000..7d9e8af
--- /dev/null
+++ b/data/sounds/newwavelabs/DonMessWivIt.wav
Binary files differ
diff --git a/data/sounds/newwavelabs/HalfwayHome.ogg b/data/sounds/newwavelabs/HalfwayHome.ogg
new file mode 100644
index 0000000..4ece7ca
--- /dev/null
+++ b/data/sounds/newwavelabs/HalfwayHome.ogg
Binary files differ
diff --git a/data/sounds/newwavelabs/HalfwayHome.wav b/data/sounds/newwavelabs/HalfwayHome.wav
new file mode 100644
index 0000000..00dbacc
--- /dev/null
+++ b/data/sounds/newwavelabs/HalfwayHome.wav
Binary files differ
diff --git a/data/sounds/newwavelabs/Playa.ogg b/data/sounds/newwavelabs/Playa.ogg
new file mode 100644
index 0000000..747b699
--- /dev/null
+++ b/data/sounds/newwavelabs/Playa.ogg
Binary files differ
diff --git a/data/sounds/newwavelabs/Playa.wav b/data/sounds/newwavelabs/Playa.wav
new file mode 100644
index 0000000..6586613
--- /dev/null
+++ b/data/sounds/newwavelabs/Playa.wav
Binary files differ
diff --git a/data/sounds/newwavelabs/SilkyWay.ogg b/data/sounds/newwavelabs/SilkyWay.ogg
new file mode 100644
index 0000000..e5a38ec
--- /dev/null
+++ b/data/sounds/newwavelabs/SilkyWay.ogg
Binary files differ
diff --git a/data/sounds/newwavelabs/SilkyWay.wav b/data/sounds/newwavelabs/SilkyWay.wav
new file mode 100644
index 0000000..6becaac
--- /dev/null
+++ b/data/sounds/newwavelabs/SilkyWay.wav
Binary files differ
diff --git a/docs/html/guide/developing/updating-sdk.jd b/docs/html/guide/developing/updating-sdk.jd
deleted file mode 100644
index f65eabb..0000000
--- a/docs/html/guide/developing/updating-sdk.jd
+++ /dev/null
@@ -1,108 +0,0 @@
-page.title=Updating Your SDK
-@jd:body
-
-
-<div id="qv-wrapper">
-<div id="qv">
-<h2>Quickview</h2>
-<ul>
-  <li>Use the Android SDK and AVD Manager to 
-   install individual Android platforms, add-ons, tools
-   and documentation.</li>
-  <li>Keep your SDK up-to-date without having to install new
-   SDK directories and update your Eclipse preferences or {@code PATH} 
-   variable.</li>
-  <li>The Android SDK and AVD Manager is available only with the 
-   Android 1.6 SDK or later.</li>
-</ul>
-
-<h2>In this document</h2>
-<ol>
-  <li><a href="#Install">Installing SDK Packages</a></li>
-  <li><a href="#Add">Adding SDK Package Sites</a></li>
-</ol>
-</div>
-</div>
-
-<p>The <strong>Android SDK and AVD Manager</strong> lets you
-update your Android SDK without a visit to the
-Android Developers web site. Instead of downloading an entirely new SDK
-that includes Android platforms, tools, and documentation, you can instead
-install only the individual packages that you want.</p>
-
-<p>For example, when a new version of the Android platform is made available
-for developing applications, use the SDK and AVD Manager to install the
-platform into your existing SDK directory. You can then use the new platform
-in your <a href="{@docRoot}guide/developing/tools/avd.html">AVDs</a> and
-build your apps against it.</p>
-
-<p>The benefit to using this feature is that your SDK directory will
-remain the same. You don't need to reset the SDK location in
-your Eclipse preferences or modify your {@code PATH} environment variable,
-because all new packages are installed into your existing SDK directory.</p>
-
-
-<p>The SDK and AVD Manager can be opened in two ways:</p>
-<ul>
-  <li>Execute the 
-  <a href="{@docRoot}guide/developing/tools/othertools.html#android">{@code 
-  android}</a> tool with no options, or</li>
-  <li>From Eclipse, select <strong>Window</strong> > <strong>Android 
-  SDK and AVD Manager</strong>.</li>
-</ul>
-
-<p>The screenshot below shows the Android SDK and AVD Manager
-with the Available Packages open.</p>
-
-<img src="{@docRoot}images/sdk_manager_packages.png" alt="" />
-
-
-<h2 id="Install">Installing SDK Packages</h2>
-
-<p>When a new Android SDK platform, add-on, set of development tools or
-documentation becomes available, you can quickly download and
-install them into your existing Android SDK:</p>
-
-<ol>
-  <li>Select <strong>Available Packages</strong> in the left panel.
-  This will reveal all packages currently available for download.</li>
-  <li>Select the packages you'd like to install and click <strong>Install
-  Selected</strong>.</li>
-  <li>Verify and accept the packages you want and click <strong>Install
-  Accepted</strong>. The packages will now be installed into your existing
-  Android SDK directories.</li>
-</ol>
-
-<p>New platforms are automatically saved into the 
-<code><em>&lt;sdk_dir>/</em>platforms/</code> directory of your SDK;
-new add-ons are saved in the <code><em>&lt;sdk_dir>/</em>add-ons/</code>
-directory; and new documentation is saved in the existing
-<code><em>&lt;sdk_dir>/</em>docs/</code> directory (old docs are replaced).</p>
-
-<p class="note"><strong>Tip:</strong>
-Use the "Display updates only" checkbox to show only the packages
-you do not have.</p>
-
-
-<h2 id="Add">Adding SDK Package Sites</h2>
-
-<p>By default, <strong>Available Packages</strong> only shows 
-the Google repository for Android SDK packages and Google API
-add-ons. You can add additional sites that host
-Android SDK add-ons, then download add-on packages from them.</p>	
-
-<p>For example, a mobile carrier or hardware manufacturer may offer additional
-API libraries that are supported by their own Android-powered devices. 
-In order for you to develop using their libraries, you may need to install an 
-Android SDK add-on.
-If the carrier or manufacturer has hosted an add-on repository file on their
-web site, add their site to the SDK and AVD Manager:</p>
-<ol>
-  <li>Select <strong>Available Packages</strong> in the left panel.</li>
-  <li>Click <strong>Add Site</strong> and enter the URL of the 
-{@code repository.xml} file. Click <strong>OK</strong>.</li>
-</ol>
-<p>Any SDK packages available from the web site will now be listed and
-available for you to install in your existing Android SDK.</p>
-
-
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index f6718e1..264fe54 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -239,7 +239,6 @@
       <li><a href="<?cs var:toroot ?>guide/developing/debug-tasks.html">
             <span class="en">Debugging Tasks</span>
           </a></li>
-      <li><a href="<?cs var:toroot ?>guide/developing/updating-sdk.html">Updating Your SDK</a></li>
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/developing/tools/index.html">
             <span class="en">Tools</span>
diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd
index c0c0b1b..4e4ca14 100644
--- a/docs/html/guide/topics/ui/dialogs.jd
+++ b/docs/html/guide/topics/ui/dialogs.jd
@@ -624,7 +624,7 @@
 AlertDialog alertDialog;
 
 Context mContext = getApplicationContext();
-LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER);
+LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
 View layout = inflater.inflate(R.layout.custom_dialog,
                                (ViewGroup) findViewById(R.id.layout_root));
 
diff --git a/docs/html/guide/tutorials/localization/index.jd b/docs/html/guide/tutorials/localization/index.jd
index 19f9eb3..d31eb10 100755
--- a/docs/html/guide/tutorials/localization/index.jd
+++ b/docs/html/guide/tutorials/localization/index.jd
@@ -76,7 +76,7 @@
 (<code>res/values/</code>). Most of the localization work you do later in this

 tutorial will involve adding more subdirectories to the <code>res/</code>

 directory.</p>

-    <img src="../../../images/hello_l10n/plain_project.png" alt="plain project" width="194"

+    <img src="{@docRoot}images/hello_l10n/plain_project.png" alt="plain project" width="194"

 height="229">

   </li>

   <li>Open the <code>res/layout/main.xml</code> file and replace it with the

@@ -192,7 +192,7 @@
 

 <p>The project structure now looks like this:</p>

 

-  <img src="../../../images/hello_l10n/nonlocalized_project.png" alt="nonlocalized" width="394"

+  <img src="{@docRoot}images/hello_l10n/nonlocalized_project.png" alt="nonlocalized" width="394"

 height="320">

 

 <p class="note"><strong>Tip:</strong> If you will want to run the application on

@@ -215,9 +215,9 @@
     <th scope="col">After clicking the flag, in any locale:</th>

   </tr>

   <tr>

-    <td valign="top"><img src="../../../images/hello_l10n/nonlocalized_screenshot1.png"

+    <td valign="top"><img src="{@docRoot}images/hello_l10n/nonlocalized_screenshot1.png"

 alt="nonlocalized" width="321" height="366"></td>

-    <td><img src="../../../images/hello_l10n/nonlocalized_screenshot2.png" alt="nonlocalized2"

+    <td><img src="{@docRoot}images/hello_l10n/nonlocalized_screenshot2.png" alt="nonlocalized2"

 width="321" height="366"></td>

   </tr>

 </table>

@@ -400,29 +400,34 @@
 

 <h3 id="localize_strings">Localize the Strings</h3>

 

-<p>The application requires  three more <code>strings.xml</code> files, one each

-for German, French, and Japanese. In this example, we will start by copying

-<code>res/values/strings.xml</code> into new

-<code>res/values-<em>&lt;qualifier&gt;</em>/strings.xml</code> files.</p>

-

-<p>Under the <code>res/</code> directory, create the three new directories and

-copy <code>res/values/strings.xml</code> into each of them. For example, using

-Eclipse you could do it like this:</p>

+<p>The application requires three more <code>strings.xml</code> files, one 

+each for German, French, and Japanese. To create these resource files within 

+Eclipse:</p>

 

 <ol>

-  <li>Right-click the <code>res/values/</code> folder and select Copy.</li>

-  <li>Right-click on the <code>res/</code> folder and select Paste. Rename the

-folder <code>values-de </code>and click OK.<br>

-    <img src="../../../images/hello_l10n/copy_res_files.png" alt="res_file_copy" width="557"

-height="181" style="margin:15px"></li>

-  <li>Repeat steps 1 and 2 two more times, for <code>values-fr</code>, and

-<code>values-ja</code>. Now the project includes these new files, all still

-containing British English text strings: <br />

+<li>Select <strong>File</strong> &gt; <strong>New</strong> &gt; <strong>Android 

+XML File</strong> to open the New Android XML File wizard. You can also open 

+the wizard by clicking its icon in the toolbar:<br />

+<img src="{@docRoot}images/hello_l10n/xml_file_wizard_shortcut.png" 

+alt="file_wizard_shortcut" width="297"

+height="90" style="margin:15px"></li>

+  <li>Select L10N for the Project field, and type <code>strings.xml</code> into 

+the File field. In the left-hand list, select Language, then click the right arrow.<br>

+<img src="{@docRoot}images/hello_l10n/xml_wizard1.png" alt="res_file_copy" width="335"

+height="406" style="margin:15px"></li>

+  <li>Type <code>de</code> in the Language box and click Finish.<br>

+    <img src="{@docRoot}images/hello_l10n/xml_wizard2.png" alt="res_file_copy" width="306"

+height="179">

+<p>A new file, <code>res/values-de/strings.xml</code>, now appears among the project 

+files.</p></li>

+<li>Repeat the steps twice more, for the language codes <code>fr</code> and	

+	<code>ja</code>.

+Now the project includes these new skeleton files: <br />

     <code>res/<strong>values-de</strong>/strings.xml</code><br />

     <code>res/<strong>values-fr</strong>/strings.xml</code><br />

     <code>res/<strong>values-ja</strong>/strings.xml</code><br />

   </li>

-  <li>Replace the strings in the three new files with localized text. To do

+  <li>Add localized text to the new files. To do

 this, open the <code>res/values-<em>&lt;qualifier&gt;</em>/strings.xml</code> files and

 replace the code as follows:</li>

 </ol>

@@ -526,12 +531,12 @@
 use the  Custom Locale application, which is available in the Application

 tab:</p>

 

-<p><img src="../../../images/hello_l10n/custom_locale_app.png" alt="custom locale app" width="163"

+<p><img src="{@docRoot}images/hello_l10n/custom_locale_app.png" alt="custom locale app" width="163"

 height="158" style="margin-left:15px"></p>

 

 <p>To switch to a new locale, long-press a  locale name:</p>

 

-<p><img src="../../../images/hello_l10n/using_custom_locale.png" alt="using custom locale"

+<p><img src="{@docRoot}images/hello_l10n/using_custom_locale.png" alt="using custom locale"

 width="512" height="299" style="margin-left:15px"></p>

 

 <p>For a list of supported locales, see the 

@@ -549,14 +554,14 @@
   <tr>

     <td>German / Germany

     	<br />Specifically supported by the Hello, L10N application.</td>

-    <td><img src="../../../images/hello_l10n/german_screenshot.png" alt="custom locale app"

+    <td><img src="{@docRoot}images/hello_l10n/german_screenshot.png" alt="custom locale app"

 width="321" height="175" align="right"

 style="margin-left:10px;margin-right:20px"></td>

   </tr>

   <tr>

     <td>French / Canada

     	<br />Specifically supported by the Hello, L10N application.</td>

-    <td><img src="../../../images/hello_l10n/frenchCA_screenshot.png" alt="custom locale app"

+    <td><img src="{@docRoot}images/hello_l10n/frenchCA_screenshot.png" alt="custom locale app"

 width="321" height="175" align="right"

 style="margin-left:10px;margin-right:20px"></td>

   </tr>

@@ -564,7 +569,7 @@
     <td>German / Switzerland

     	<br />Only the language is specifically supported by 

 the Hello, L10N  application.</td>

-    <td><img src="../../../images/hello_l10n/germanCH_screenshot.png" alt="custom locale app"

+    <td><img src="{@docRoot}images/hello_l10n/germanCH_screenshot.png" alt="custom locale app"

 width="321" height="175" align="right"

 style="margin-left:10px;margin-right:20px">`</td>

   </tr>

@@ -572,7 +577,7 @@
     <td>Japanese

     	<br />Specifically supported by  the Hello, L10N  application. 

 	</td>

-    <td><img src="../../../images/hello_l10n/japanese_screenshot.png" alt="custom locale app"

+    <td><img src="{@docRoot}images/hello_l10n/japanese_screenshot.png" alt="custom locale app"

 width="321" height="220" align="right"

 style="margin-left:10px;margin-right:20px">`</td>

   </tr>

@@ -580,7 +585,7 @@
     <td>Romansh / Switzerland (custom locale <code>rm_CH</code>)

     	<br />Not specifically supported  by  the Hello, L10N 

 application, so the application uses the default resources.</td>

-    <td><img src="../../../images/hello_l10n/romanshCH_screenshot.png" alt="custom locale app"

+    <td><img src="{@docRoot}images/hello_l10n/romanshCH_screenshot.png" alt="custom locale app"

 width="321" height="175" align="right"

 style="margin-left:10px;margin-right:20px"></td>

   </tr>

diff --git a/docs/html/images/hello_l10n/xml_file_wizard_shortcut.png b/docs/html/images/hello_l10n/xml_file_wizard_shortcut.png
new file mode 100755
index 0000000..f72554d
--- /dev/null
+++ b/docs/html/images/hello_l10n/xml_file_wizard_shortcut.png
Binary files differ
diff --git a/docs/html/images/hello_l10n/xml_wizard1.png b/docs/html/images/hello_l10n/xml_wizard1.png
new file mode 100755
index 0000000..35dc09f
--- /dev/null
+++ b/docs/html/images/hello_l10n/xml_wizard1.png
Binary files differ
diff --git a/docs/html/images/hello_l10n/xml_wizard2.png b/docs/html/images/hello_l10n/xml_wizard2.png
new file mode 100755
index 0000000..6bcd28b
--- /dev/null
+++ b/docs/html/images/hello_l10n/xml_wizard2.png
Binary files differ
diff --git a/docs/html/sdk/2.0_r1/installing.jd b/docs/html/sdk/2.0_r1/installing.jd
new file mode 100644
index 0000000..fd269dc
--- /dev/null
+++ b/docs/html/sdk/2.0_r1/installing.jd
@@ -0,0 +1,389 @@
+page.title=Installing the Android 2.0 SDK
+sdk.preview=0
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#Preparing">Prepare for Installation</a></li>
+    <li><a href="#Installing">Install the SDK</a></li>
+    <li><a href="#InstallingADT">Install the ADT Plugin for Eclipse</a></li>
+    <li><a href="#sdkContents">SDK Contents</a></li>
+    <li><a href="#NextSteps">Next Steps</a></li>
+    <li><a href="#InstallationNotes">Installation Notes</a></li>
+    <li><a href="#Troubleshooting">Troubleshooting ADT Installation</a></li>
+  </ol>
+
+</div>
+</div>
+
+<p>This page describes how to install the Android SDK and set up your
+development environment for the first time.</p>
+
+<p>If you encounter any problems during installation, see the 
+<a href="#InstallationNotes">Installation Notes</a> at the bottom of
+this page.</p>
+
+<h4>Updating?</h4>
+<p>If you have already installed an earlier version
+of the Android SDK, please instead read <a href="{@docRoot}sdk/updating-sdk.html">Updating Your SDK</a>.
+</p>
+
+
+<h2 id="Preparing">Prepare 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 in 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.4 or newer is recommended). 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="Installing">Install the SDK</h2>
+
+<p>After downloading the Android SDK, unpack the Android SDK .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>. </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 <code>PATH</code>. 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 OS X, 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 <code>PATH</code> 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 (ADT) 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="#NextSteps">Next Steps</a>).</p>
+
+
+<h2 id="InstallingADT">Install 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&mdash;skip to <a href="#NextSteps">Next Steps</a>.)</p>
+
+<p>Once you have the Eclipse IDE installed, as described in <a
+href="#Preparing">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.4 (Ganymede)</th><th>Eclipse 3.5 (Galileo)</th></tr>
+<tr>
+<td width="45%">
+<!-- 3.4 steps -->
+<ol>
+    <li>Start Eclipse, then select <strong>Help</strong> &gt; <strong>Software Updates...</strong>. 
+        In the dialog that appears, click the <strong>Available Software</strong> tab. </li>
+    <li>Click <strong>Add Site...</strong> </li>
+    <li>In the Add Site dialog that appears, enter this URL in the "Location" field:
+      <pre style="margin-left:0">https://dl-ssl.google.com/android/eclipse/</pre>
+        <p>Note: 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>
+<td>
+<!-- 3.5 steps -->
+<ol>
+    <li>Start Eclipse, then select <strong>Help</strong> &gt; <strong>Install
+        New Softare</strong>. </li>
+    <li>In the Available Software dialog, click <strong>Add...</strong>.</li>
+    <li>In the Add Site dialog that appears, enter a name for the remote site
+        (e.g., "Android Plugin") in the "Name" field. 
+        <p>In the "Location" field, enter this URL:</p>
+        <pre>https://dl-ssl.google.com/android/eclipse/</pre>
+        <p>Note: If you have trouble aqcuiring the plugin, you can try
+           using "http" in the 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 now see "Developer
+        Tools" added to the list. Select the checkbox next to Developer Tools, 
+        which will automatically select the nested tools Android DDMS and Android 
+        Development Tools. 
+        Click <strong>Next</strong>. </li>
+    <li>In the resulting Install Details dialog, the Android DDMS and Android 
+        Development Tools features are listed. Click <strong>Next</strong> to 
+        read and accept the license agreement and install any dependencies, 
+        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 OS X: <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="#NextSteps">Next Steps</a> section for suggestions on how to start. </p>
+
+
+<h2 id="sdkContents">Contents of the SDK</h2>
+
+<p>Once you've downloaded and unpacked the SDK, open the SDK directory 
+and take a look at what's inside.</p>
+
+<p>The table below describes the SDK directory contents. </p>
+
+<table>
+<tr>
+<th colspan="3">Name</th><th>Description</th>
+</tr>
+<tr>
+<td colspan="3"><code>add-ons/</code></td>
+<td>Contains add-ons to the Android SDK development
+environment, which let you develop against external libraries that are available on some
+devices. </td>
+</tr>
+<tr>
+<td colspan="3"><code>docs/</code></td>
+<td>A full set of documentation in HTML format, including the Developer's Guide,
+API Reference, and other information.</td>
+</tr>
+<tr>
+<td colspan="3"><code>platforms/</code></td>
+<td>Contains a set of Android platform versions that you can develop
+applications against, each in a separate directory.  </td>
+</tr>
+<tr>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td colspan="2"><code>&lt;platform&gt;/</code></td>
+<td>Platform version directory, for example "Android 1.6". All platform version 
+directories contain a similar set of files and subdirectory structure.</td>
+</tr>
+
+<tr>
+<td style="width:2em;border-bottom-color:white;">&nbsp;</td>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td><code>data/</code></td>
+<td>Storage area for default fonts and resource definitions.</td>
+</tr>
+<tr>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td><code>images/</code></td>
+<td>Storage area for default disk images, including the Android system image, 
+the default userdata image, the default ramdisk image, and more. The images 
+are used in emulator sessions.</td>
+</tr>
+<tr>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td><code>samples/</code></td>
+<td>Contains a wide variety of sample applications that you can load as projects
+into your development environment, compile, and run on the emulator.</td>
+</tr>
+<tr>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td><code>skins/</code></td>
+<td>A set of emulator skins available for the platform version. Each skin is
+designed for a specific screen resolution.</td>
+</tr>
+<tr>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td><code>templates/</code></td>
+<td>Storage area for file templates used by the SDK development tools.</td>
+</tr>
+<tr>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td style="width:2em;border-bottom-color:white;"></td>
+<td><code>tools/</code></td>
+<td>Any development tools that are specific to the platform version.</td>
+</tr>
+<tr>
+<td style="width:2em;"></td>
+<td style="width:2em;"></td>
+<td><code>android.jar</code></td>
+<td>The Android library used when compiling applications against this platform
+version.</td>
+</tr>
+<tr>
+<td colspan="3"><code>tools/</code></td>
+<td>Contains the set of development and profiling tools available to you, such
+as the emulator, the <code>android</code> tool, adb, ddms, and more.</td>
+</tr>
+<tr>
+<td colspan="3"><code>RELEASE_NOTES.html</code></td>
+<td>A file that loads the local version of the SDK release notes, if
+available.</td>
+</tr>
+<tr>
+<td colspan="3"><code>documentation.html</code></td>
+<td>A file that loads the entry page for the local Android SDK
+documentation.</td>
+</tr>
+
+</table>
+
+<h2 id="InstallationNotes">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="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>
+
+
+<h2 id="Troubleshooting">Troubleshooting ADT Installation</h2>
+
+<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 OS X, <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 it:</p>
+
+<ol>
+  <li><a href="http://developer.android.com/sdk/preview/index.html">Download the
+      ADT Plugin zip file</a> (do not unpack it).</li>
+  <li>Follow steps 1 and 2 in the <a href="#InstallingADT">default install 
+      instructions</a> (above).</li>
+  <li>In the Add Site dialog, click <strong>Archive</strong>.</li>
+  <li>Browse and select the downloaded zip file.</li>
+  <li>In Eclipse 3.5 only, enter a name for the local update site (e.g.,
+      "Android Plugin") in the "Name" field.</li>
+  <li>Click <strong>OK</strong>.
+  <li>Follow the remaining procedures as listed for 
+      <a href="#InstallingADT">default installation</a> above,
+      starting from step 4.</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>
+
+
diff --git a/docs/html/sdk/download.jd b/docs/html/sdk/download.jd
index 1712ae6..76f1213 100644
--- a/docs/html/sdk/download.jd
+++ b/docs/html/sdk/download.jd
@@ -57,15 +57,11 @@
 <div class="special" id="next-steps" style="display:none">
   <h2>Thank you for downloading the Android SDK!</h2>
   <p>Your download should be underway. If not, <a id="click-download">click here to start the download</a>.</p>
-  <p>If you are upgrading from a previously installed version of the Android SDK, see
-    <a href="upgrading.html" class="addVersionPath">Upgrading the SDK</a>.</p>
-  <p>If you are installing for the first time, read 
-    <a href="installing.html" class="addVersionPath">Installing the Android SDK</a> to get your environment set up.
-    Once you have completed your installation, visit the <em>Dev Guide</em> tab and begin with the 
-    <a href="/guide/tutorials/hello-world.html">Hello World</a> tutorial to create your first
-    Android application. From there, learn more about Android with the 
-    <a href="/guide/topics/fundamentals.html">Application Fundamentals</a> documentation.</p>
-  <p>If you want to re-read the license agreement, it's available to you in the <em>SDK</em> tab.</p>
+  <p>To set up your Android development environment, please read the guide to
+    <a href="installing.html" class="addVersionPath">Installing the Android SDK</a>.
+    Once you have completed the installation, see the
+    <a href="/guide/index.html">Dev Guide</a> for documentation about
+    developing Android applications.</p>
 </div>
 
 <script type="text/javascript">
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 2ac7688..e82ed34 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -1,6 +1,104 @@
-sdk.redirect=true
+page.title=Android 2.0 SDK, Release 1
+sdk.redirect=0
+sdk.version=2.0
+
+sdk.date=October 2009
+
+sdk.win_download=android-sdk-windows-2.0_r1.zip
+sdk.win_bytes=
+sdk.win_checksum=
+
+sdk.mac_download=android-sdk-mac_x86-2.0_r1.zip
+sdk.mac_bytes=
+sdk.mac_checksum=
+
+sdk.linux_download=android-sdk-linux_x86-2.0_r1.tgz
+sdk.linux_bytes=
+sdk.linux_checksum=
+
+adt.zip_download=ADT-0.9.4.zip
+adt.zip_version=0.9.4
+adt.zip_bytes=
+adt.zip_checksum=
 
 @jd:body
 
+<p>For more information on this SDK release, read the
+<a href="{@docRoot}sdk/RELEASENOTES.html">Release Notes</a>.</p>
+
+<p>For setup procedures, read the 
+<a href="{@docRoot}sdk/{@sdkCurrent}/installing.html">Installing</a> guide.</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><em>&lt;sdk&gt;</em>/tools/</code> directory.</p>
+
+<h4 id="system_images">Android Platforms</h4>
+
+<p>This SDK includes only the Android {@sdkCurrentVersion} platform version for developing Android
+applications. With this platform, both the fully compliant Android {@sdkCurrentVersion} library
+and system image are provided. For more information about this platform version &mdash;
+features, applications included, localizations, API changes, and so on &mdash;
+see the <a href="{@docRoot}sdk/android-{@sdkCurrentVersion}.html">Android {@sdkCurrentVersion}
+Version Notes</a>.</p>
+
+<p>Although only one platform version is included in the SDK, you do not need to
+install a separate Android SDK for each platform version on which would like to develop
+applications. Once you install the SDK from this page, you can easily install
+additional Android platform versions using the Android SDK and AVD Manager.
+For more information about adding platform versions to your SDK,
+read <a href="{@docRoot}sdk/updating-sdk.html">Updating Your SDK</a>.</p>
+
+
+<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-ons listed below. The Android system API Level required by
+each 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%">5</td>
+<td  width="5%">&nbsp;</td>
+<td>Includes the com.google.android.maps external library, a compliant
+Android 2.0 system image, a {@link android.location.Geocoder Geocoder}
+backend service implementation, documentation, and sample code. </td>
+</tr>
+</table>
+
+
+<h4 id="samples">Sample Code and Applications</h4>
+
+<p>You can look at a variety of sample applications in the <a
+href="{@docRoot}guide/samples/index.html">Dev Guide</a> and access the sample
+code itself in the <code><em>&lt;sdk&gt;</em>/platforms/<em>&lt;platform&gt;</em>/samples/</code>
+directory of the SDK package. Note that each platform version includes its own set of
+sample applications.</p>
+
+
+<h4 id="documentation">Documentation</h4>
+
+<p>The SDK package includes a full set of local documentation. To view it, open
+the <code><em>&lt;sdk&gt;</em>/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 by hovering over methods and class names.</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/requirements.jd b/docs/html/sdk/requirements.jd
new file mode 100644
index 0000000..97db36d
--- /dev/null
+++ b/docs/html/sdk/requirements.jd
@@ -0,0 +1,54 @@
+page.title=System Requirements
+@jd:body
+
+<p>The sections below describe the system and software requirements for developing 
+Android applications using the Android Development Tools, revision 3. </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 Hardy Heron)
+    <ul>
+      <li>64-bit distributions must be capable of running 32-bit applications. 
+      For information about how to add support for 32-bit applications, see
+      the <a href="installing.html#InstallationNotes">Installation Notes</a>.</li>
+    </ul>
+  </li>
+</ul>
+
+<h3>Supported Development Environments</h3>
+<ul>
+  <li>Eclipse IDE
+    <ul>
+      <li><a href="http://www.eclipse.org/downloads/">Eclipse</a> 3.4 (Ganymede) or 3.5 (Galileo)
+        <ul>
+        <li>Note: Eclipse 3.3 has not been fully tested with ADT 0.9.3 and support can no longer be guaranteed. We suggest you upgrade to 
+          Eclipse 3.4 or 3.5.</li>
+        <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>
+
+<h3>Hardware requirements</h3>
+<ul>
+  <li>For the base SDK package, at least 600MB of available disk space. For each platform downloaded into the SDK, an additional 100MB is needed. </li>
+</ul>
+
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 143a38d..b75fe9b 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -13,10 +13,7 @@
       <span style="display:none" class="zh-TW">目前 SDK 發行版本</span>
     </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/<?cs
-        if:sdk.preview ?>preview<?cs
-			  else ?><?cs var:sdk.current ?><?cs
-			  /if ?>/index.html">
+      <li><a href="<?cs var:toroot ?>sdk/index.html">
           <span class="en">Download</span>
           <span style="display:none" class="de">Herunterladen</span>
           <span style="display:none" class="es">Descargar</span>
@@ -26,10 +23,7 @@
           <span style="display:none" class="zh-CN">下载</span>
           <span style="display:none" class="zh-TW">下載</span>
         </a></li>
-      <li><a href="<?cs var:toroot ?>sdk/<?cs
-        if:sdk.preview ?>preview<?cs
-			  else ?><?cs var:sdk.current ?><?cs
-			  /if ?>/installing.html">
+      <li><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/installing.html">
           <span class="en">Installing</span>
           <span style="display:none" class="de">Installieren</span>
           <span style="display:none" class="es">Instalación</span>
@@ -39,14 +33,8 @@
           <span style="display:none" class="zh-CN">安装</span>
           <span style="display:none" class="zh-TW">安裝</span>
         </a></li>
-      <li><a href="<?cs var:toroot ?>sdk/<?cs
-        if:sdk.preview ?>preview<?cs
-			  else ?><?cs var:sdk.current ?><?cs
-			  /if ?>/upgrading.html">Upgrading</a></li>
-      <li><a href="<?cs var:toroot ?>sdk/<?cs
-        if:sdk.preview ?>preview<?cs
-			  else ?><?cs var:sdk.current ?><?cs
-			  /if ?>/requirements.html">System Requirements</a></li>
+      <li><a href="<?cs var:toroot ?>sdk/updating-sdk.html">Updating Your SDK</a></li>
+      <li><a href="<?cs var:toroot ?>sdk/requirements.html">System Requirements</a></li>
     </ul><?cs 
    else ?> <?cs # else "if NOT online" ... ?>
     <h2>
@@ -55,10 +43,7 @@
    /if ?> <?cs # end of "if/else online" ... ?>
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/terms.html">SDK Terms and Conditions</a></li>
-      <li><a href="<?cs var:toroot ?><?cs 
-        if:sdk.current == "preview" ?>sdk/preview/index.html<?cs 
-        else ?>sdk/RELEASENOTES.html<?cs 
-        /if ?>">SDK Release Notes</a></li>
+      <li><a href="<?cs var:toroot ?>sdk/RELEASENOTES.html">SDK Release Notes</a></li>
     </ul>
   </li><?cs 
  if:android.whichdoc == "online" ?>
@@ -74,11 +59,34 @@
       <span style="display:none" class="zh-TW">系統影像版本資訊</span>
     </h2>
     <ul>
+      <li><a href="<?cs var:toroot ?>sdk/android-2.0.html">Android 2.0 Version Notes</a></li>
       <li><a href="<?cs var:toroot ?>sdk/android-1.6.html">Android 1.6 Version Notes</a></li>
-      <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>
+  <!--    <li class="toggle-list"><div><a href="#" onclick="toggle(this.parentNode.parentNode,true); return false;">More</a></div>
+        <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>
     </ul>
   </li>
+<!--
+  <li>
+    <h2>
+      <span class="en">Developer Tools</span>
+      <span style="display:none" class="de"></span>
+      <span style="display:none" class="es"></span>
+      <span style="display:none" class="fr"></span>
+      <span style="display:none" class="it"></span>
+      <span style="display:none" class="ja"></span>
+      <span style="display:none" class="zh-CN"></span>
+      <span style="display:none" class="zh-TW"></span>
+    </h2>
+    <ul>
+      <li><a href="<?cs var:toroot ?>sdk/tools.html">Tools Revision 3</a></li>
+      <li><a href="<?cs var:toroot ?>sdk/adt.html">"ADT Plugin for Eclipse, 0.9.4</a></li>
+    </ul>
+  </li>
+-->
   <li>
     <h2>Native Development Tools</h2>
     <ul>
@@ -97,6 +105,7 @@
         <span style="display:none" class="zh-TW">較舊的 SDK 發行版本</span>
     </h2>
     <ul>
+      <li><a href="<?cs var:toroot ?>sdk/1.6_r1/index.html">Android 1.6 SDK, r1</a></li>
       <li><a href="<?cs var:toroot ?>sdk/1.5_r3/index.html">Android 1.5 SDK, r3</a></li>
       <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>
diff --git a/docs/html/sdk/updating-sdk.jd b/docs/html/sdk/updating-sdk.jd
new file mode 100644
index 0000000..db1e8db
--- /dev/null
+++ b/docs/html/sdk/updating-sdk.jd
@@ -0,0 +1,181 @@
+page.title=Updating Your SDK
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Quick view</h2>
+<ul>
+  <li>Use the Android SDK and AVD Manager to 
+   keep your SDK up-to-date without having to install new
+   SDK directories.</li>
+  <li>The Android SDK and AVD Manager is available only with the 
+   Android 1.6 SDK or later.</li>
+  <li>The Eclipse ADT plugin may require an update when installing
+   new tools or system images.</li>
+</ul>
+
+<h2>In this document</h2>
+<ol>
+  <li><a href="#InstallingComponents">Installing SDK Components</a>
+    <ol>
+      <li><a href="#AddingSites">Adding New Sites</a></li>
+    </ol>
+  </li>
+  <li><a href="#UpdatingAdt">Updating the Eclipse ADT Plugin</a></li>
+</ol>
+</div>
+</div>
+
+
+<p>Updating your Android SDK is fast and easy. To perform an update, use the
+<strong>Android SDK and AVD Manager</strong>
+to install or update the individual SDK components that you need.</p>
+
+<p>It only takes a couple of clicks to install
+individual versions of the Android platform, new development tools, new documentation, and
+SDK add-ons. The new SDK components are automatically installed into your existing SDK 
+directory, so you don't need to update your development environment to specify a
+new SDK location.</p>
+
+<p>Because each version of the Android platform can be installed as an individual component
+of your SDK, you can customize your development environment to the Android platforms
+you are targetting. Testing your app on multiple versions of
+the platform is very important in order to successfully operate on as many devices as possible.
+Be sure to install each version of the Android platform with which your app is compatible, then test
+your apps on <a href="{@docRoot}guide/developing/tools/avd.html">AVDs</a> that run each platform.</p>
+
+<p>If you develop applications using Eclipse, you may also need to update
+your ADT plugin when you update your development tools or in order to compile
+against a new version of the platform. See the 
+<a href="{@docRoot}sdk/RELEASENOTES.html">SDK Release Notes</a> for ADT compatibility.</p>
+
+
+
+<h2 id="InstallingComponents">Installing SDK Components</h2>
+
+<p>Use the Android SDK and AVD Manager to install new SDK components. 
+To launch the SDK and AVD Manager:</p>
+<ul>
+  <li>Execute the <a 
+  href="{@docRoot}guide/developing/tools/othertools.html#android">{@code android}</a> tool
+  command with no options.</li>
+  <li>Or from Eclipse, select <strong>Window</strong> &gt;<strong>Android SDK and AVD
+  Manager</strong>.</li>
+</ul>
+
+<img src="{@docRoot}images/sdk_manager_packages.png" alt="" style="float:right" />
+
+<p>When a new platform version, add-on, set of development tools or
+documentation becomes available, you can quickly
+install them into your existing Android SDK:</p>
+
+<ol>
+  <li>Select <strong>Available Components</strong> in the left panel.
+  This will reveal all components currently available for download.</li>
+  <li>Select the components you'd like to install and click <strong>Install
+  Selected</strong>.</li>
+  <li>Verify and accept the components you want and click <strong>Install
+  Accepted</strong>. The components will now be installed into your existing
+  Android SDK directories.</li>
+</ol>
+
+<p>New platforms are automatically saved into the 
+<code><em>&lt;sdk>/</em>platforms/</code> directory of your SDK;
+new add-ons are saved in the <code><em>&lt;sdk>/</em>add-ons/</code>
+directory; and new documentation is saved in the existing
+<code><em>&lt;sdk>/</em>docs/</code> directory (old docs are replaced).</p>
+
+<p class="note"><strong>Tip:</strong>
+Use the "Display updates only" checkbox to show only the components
+you do not have.</p>
+
+
+<h3 id="AddingSites">Adding New Sites</h3>
+
+<p>By default, <strong>Available Components</strong> only shows 
+the Google repository for Android SDK components and Google API
+add-ons. You can add additional sites that host
+Android SDK add-ons, then download SDK add-ons from them.</p>	
+
+<p>For example, a mobile carrier or hardware manufacturer may offer additional
+API libraries that are supported by their own Android-powered devices. 
+In order to develop using their libraries, you must install their
+Android SDK add-on.
+If the carrier or manufacturer has hosted an add-on repository file on their
+web site, add their site to the SDK and AVD Manager:</p>
+<ol>
+  <li>Select <strong>Available Components</strong> in the left panel.</li>
+  <li>Click <strong>Add Site</strong> and enter the URL of the 
+{@code repository.xml} file. Click <strong>OK</strong>.</li>
+</ol>
+<p>Any SDK components available from the site will now be listed under
+<strong>Available Components</strong>.</p>
+
+
+
+
+
+<h2 id="UpdatingAdt">Updating the Eclipse ADT Plugin</h2>
+
+<p>You may need to update your ADT plugin depending on what version of the
+development tools you are using and what version of the Android platform you are
+compiling against. It's easy to update your plugin through Eclipse and we
+recommend that you stay up-to-date in order to avoid any problems.</p>
+
+<p>With the latest version of ADT, you can still compile existing applications against 
+previous versions of the Android platform. However, the latest ADT may
+not work with a previous version of the development tools. See the
+Android development tools release notes for compatibility information.</p>
+
+<p>To update ADT, follow the procedure below for your respective version of Eclipse.</p>
+
+<table style="font-size:100%">
+<tr><th>Eclipse 3.4 (Ganymede)</th><th>Eclipse 3.5 (Galileo)</th></tr>
+<tr>
+<td width="50%">
+<!-- 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>Select the checkboxes next to Android DDMS and Android Developer Tools, 
+      then click  <strong>Update</strong>.</li>
+    <li>In the resulting Available Updates dialog, ensure that both Android DDMS 
+      and Android Development Tools are selected, then click 
+      <strong>Next</strong>.</li>
+    <li>Read and accept the license agreement and then click <strong>Finish</strong>.
+      This will download and install the latest version of Android DDMS and 
+      Android Development Tools.</li>
+    <li>Restart Eclipse.</li>
+</ol>
+</td>
+<td>
+<!-- 3.5 steps -->
+<ol>
+    <li>Select <strong>Help</strong> &gt; <strong>Check for Updates</strong>. </li>
+    <li>In the resulting Available Updates dialog, locate the Android DDMS and 
+        Android Development Tools features in the list and ensure that the checkboxes
+        next to them are selected. Click <strong>Next</strong>. 
+        <p>If the Available Updates dialog does not list Android DDMS and Android 
+           Development tools, make sure that you have set up a remote update site 
+           for them, as described in 
+           <a href="installing.html#InstallingADT">Installing the ADT Plugin</a>. 
+        </p></li>
+    <li>In the Update Details dialog, click <strong>Next</strong>.</li>
+    <li>Read and accept the license agreement and then click <strong>Finish</strong>.
+      This will download and install the latest version of Android DDMS and 
+      Android Development Tools.</li>
+    <li>Restart Eclipse.</li>
+</ol>
+</td>
+</tr>
+</table>
+
+<p>If you encounter problems with this update procedure, try performing a fresh
+installation. Fully remove your existing ADT Plugin as described in <a
+href="{@docRoot}sdk/1.5_r3/upgrading.html#uninstallAdt">Uninstall your previous
+ADT plugin</a> and then follow the guide to <a
+href="{@docRoot}sdk/{@sdkCurrent}/installing.html#InstallingADT">Installing the ADT Plugin for
+Eclipse</a>.</p>
+
+
diff --git a/graphics/java/android/renderscript/SimpleMesh.java b/graphics/java/android/renderscript/SimpleMesh.java
index 0ad093e..3d10e3b 100644
--- a/graphics/java/android/renderscript/SimpleMesh.java
+++ b/graphics/java/android/renderscript/SimpleMesh.java
@@ -228,17 +228,17 @@
                 mVtxData[mVtxCount++] = mB;
                 mVtxData[mVtxCount++] = mA;
             }
+            if ((mFlags & TEXTURE_0) != 0) {
+                makeSpace(2);
+                mVtxData[mVtxCount++] = mS0;
+                mVtxData[mVtxCount++] = mT0;
+            }
             if ((mFlags & NORMAL) != 0) {
                 makeSpace(3);
                 mVtxData[mVtxCount++] = mNX;
                 mVtxData[mVtxCount++] = mNY;
                 mVtxData[mVtxCount++] = mNZ;
             }
-            if ((mFlags & TEXTURE_0) != 0) {
-                makeSpace(2);
-                mVtxData[mVtxCount++] = mS0;
-                mVtxData[mVtxCount++] = mT0;
-            }
         }
 
         public void addVertex(float x, float y) {
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 303444c..d5c1594 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -42,7 +42,7 @@
     virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
-    virtual sp<IOMX>            createOMX() = 0;
+    virtual sp<IOMX>            getOMX() = 0;
 
     // Take a peek at currently playing audio, for visualization purposes.
     // This returns a buffer of 16 bit mono PCM data, or NULL if no visualization buffer is currently available.
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index e551d17..6f3ba1c 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -42,57 +42,57 @@
     typedef void *buffer_id;
     typedef void *node_id;
 
-    virtual status_t list_nodes(List<String8> *list) = 0;
+    virtual status_t listNodes(List<String8> *list) = 0;
 
-    virtual status_t allocate_node(const char *name, node_id *node) = 0;
-    virtual status_t free_node(node_id node) = 0;
+    virtual status_t allocateNode(
+            const char *name, const sp<IOMXObserver> &observer,
+            node_id *node) = 0;
 
-    virtual status_t send_command(
+    virtual status_t freeNode(node_id node) = 0;
+
+    virtual status_t sendCommand(
             node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) = 0;
 
-    virtual status_t get_parameter(
+    virtual status_t getParameter(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size) = 0;
 
-    virtual status_t set_parameter(
+    virtual status_t setParameter(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size) = 0;
 
-    virtual status_t get_config(
+    virtual status_t getConfig(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size) = 0;
 
-    virtual status_t set_config(
+    virtual status_t setConfig(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size) = 0;
 
-    virtual status_t use_buffer(
+    virtual status_t useBuffer(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer) = 0;
 
-    virtual status_t allocate_buffer(
+    virtual status_t allocateBuffer(
             node_id node, OMX_U32 port_index, size_t size,
             buffer_id *buffer) = 0;
 
-    virtual status_t allocate_buffer_with_backup(
+    virtual status_t allocateBufferWithBackup(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer) = 0;
 
-    virtual status_t free_buffer(
+    virtual status_t freeBuffer(
             node_id node, OMX_U32 port_index, buffer_id buffer) = 0;
 
-    virtual status_t observe_node(
-            node_id node, const sp<IOMXObserver> &observer) = 0;
+    virtual status_t fillBuffer(node_id node, buffer_id buffer) = 0;
 
-    virtual status_t fill_buffer(node_id node, buffer_id buffer) = 0;
-
-    virtual status_t empty_buffer(
+    virtual status_t emptyBuffer(
             node_id node,
             buffer_id buffer,
             OMX_U32 range_offset, OMX_U32 range_length,
             OMX_U32 flags, OMX_TICKS timestamp) = 0;
 
-    virtual status_t get_extension_index(
+    virtual status_t getExtensionIndex(
             node_id node,
             const char *parameter_name,
             OMX_INDEXTYPE *index) = 0;
@@ -162,7 +162,7 @@
 public:
     DECLARE_META_INTERFACE(OMXObserver);
 
-    virtual void on_message(const omx_message &msg) = 0;
+    virtual void onMessage(const omx_message &msg) = 0;
 };
 
 class IOMXRenderer : public IInterface {
diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
index 926fddb..8d76533 100644
--- a/include/private/ui/RegionHelper.h
+++ b/include/private/ui/RegionHelper.h
@@ -86,7 +86,7 @@
                         rasterizer(current);
                     }
                 }
-            } while(!spannerInner.isDone());            
+            } while(!spannerInner.isDone());
         } while(!spanner.isDone());
     }
 
@@ -220,18 +220,21 @@
         }
 
         inline void prepare(int inside) {
-            SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
-            SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
-            SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
-            SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
             if (inside == SpannerBase::lhs_before_rhs) {
+                SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
+                SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
                 SpannerBase::rhs_head = max_value;
                 SpannerBase::rhs_tail = max_value;
             } else if (inside == SpannerBase::lhs_after_rhs) {
                 SpannerBase::lhs_head = max_value;
                 SpannerBase::lhs_tail = max_value;
+                SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
+                SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
             } else {
-                // use both spans
+                SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
+                SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+                SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
+                SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
             }
         }
 
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 195ea6f..cc39dac 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -29,6 +29,8 @@
 using namespace android::renderscript;
 
 pthread_key_t Context::gThreadTLSKey = 0;
+uint32_t Context::gThreadTLSKeyCount = 0;
+pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
 
 void Context::initEGL()
 {
@@ -57,6 +59,7 @@
     configAttribsPtr[0] = EGL_NONE;
     rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));
 
+    LOGV("initEGL start");
     mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion);
 
@@ -144,6 +147,12 @@
     }
     mStateFragmentStore.mLast.clear();
     bool ret = runScript(mRootScript.get(), 0);
+
+    GLenum err = glGetError();
+    if (err != GL_NO_ERROR) {
+        LOGE("Pending GL Error, 0x%x", err);
+    }
+
     return ret;
 }
 
@@ -293,6 +302,8 @@
 
 Context::Context(Device *dev, Surface *sur, bool useDepth)
 {
+    pthread_mutex_lock(&gInitMutex);
+
     dev->addContext(this);
     mDev = dev;
     mRunning = false;
@@ -304,16 +315,18 @@
     int status;
     pthread_attr_t threadAttr;
 
-    if (!gThreadTLSKey) {
+    if (!gThreadTLSKeyCount) {
         status = pthread_key_create(&gThreadTLSKey, NULL);
         if (status) {
             LOGE("Failed to init thread tls key.");
+            pthread_mutex_unlock(&gInitMutex);
             return;
         }
-    } else {
-        // HACK: workaround gl hang on start
-        exit(-1);
     }
+    gThreadTLSKeyCount++;
+    pthread_mutex_unlock(&gInitMutex);
+
+    // Global init done at this point.
 
     status = pthread_attr_init(&threadAttr);
     if (status) {
@@ -355,10 +368,16 @@
     int status = pthread_join(mThreadId, &res);
     objDestroyOOBRun();
 
+    // Global structure cleanup.
+    pthread_mutex_lock(&gInitMutex);
     if (mDev) {
         mDev->removeContext(this);
-        pthread_key_delete(gThreadTLSKey);
+        --gThreadTLSKeyCount;
+        if (!gThreadTLSKeyCount) {
+            pthread_key_delete(gThreadTLSKey);
+        }
     }
+    pthread_mutex_unlock(&gInitMutex);
 
     objDestroyOOBDestroy();
 }
@@ -419,6 +438,7 @@
     } else {
         mVertex.set(pv);
     }
+    mVertex->forceDirty();
 }
 
 void Context::assignName(ObjectBase *obj, const char *name, uint32_t len)
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 3570e10..0dd90ed 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -53,6 +53,9 @@
     ~Context();
 
     static pthread_key_t gThreadTLSKey;
+    static uint32_t gThreadTLSKeyCount;
+    static pthread_mutex_t gInitMutex;
+
     struct ScriptTLSStruct {
         Context * mContext;
         Script * mScript;
diff --git a/libs/rs/rsProgram.h b/libs/rs/rsProgram.h
index 26b78dd..57c654f 100644
--- a/libs/rs/rsProgram.h
+++ b/libs/rs/rsProgram.h
@@ -44,6 +44,10 @@
     ObjectBaseRef<Allocation> mConstants;
 
     mutable bool mDirty;
+
+
+public:
+    void forceDirty() {mDirty = true;}
 };
 
 
diff --git a/libs/rs/rsProgramRaster.cpp b/libs/rs/rsProgramRaster.cpp
index fcf6824..51ae7cf 100644
--- a/libs/rs/rsProgramRaster.cpp
+++ b/libs/rs/rsProgramRaster.cpp
@@ -74,7 +74,7 @@
     if (mLineSmooth) {
         glEnable(GL_LINE_SMOOTH);
     } else {
-        glEnable(GL_LINE_SMOOTH);
+        glDisable(GL_LINE_SMOOTH);
     }
 
     if (rsc->checkVersion1_1()) {
diff --git a/libs/ui/tests/region.cpp b/libs/ui/tests/region.cpp
index 0deb2ba..ef15de9 100644
--- a/libs/ui/tests/region.cpp
+++ b/libs/ui/tests/region.cpp
@@ -25,9 +25,16 @@
 
 int main()
 {
+    Region empty;
     Region reg0( Rect(  0, 0,  100, 100 ) );
     Region reg1 = reg0;
     Region reg2, reg3;
+
+    Region reg4 = empty | reg1;
+    Region reg5 = reg1 | empty;
+
+    reg4.dump("reg4");
+    reg5.dump("reg5");
     
     reg0.dump("reg0");
     reg1.dump("reg1");
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 98f7ef1..cca3e9b 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -35,7 +35,7 @@
     DECODE_FD,
     CREATE_MEDIA_RECORDER,
     CREATE_METADATA_RETRIEVER,
-    CREATE_OMX,
+    GET_OMX,
     SNOOP
 };
 
@@ -123,10 +123,10 @@
         return interface_cast<IMemory>(reply.readStrongBinder());
     }
 
-    virtual sp<IOMX> createOMX() {
+    virtual sp<IOMX> getOMX() {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        remote()->transact(CREATE_OMX, data, &reply);
+        remote()->transact(GET_OMX, data, &reply);
         return interface_cast<IOMX>(reply.readStrongBinder());
     }
 };
@@ -207,9 +207,9 @@
             reply->writeStrongBinder(retriever->asBinder());
             return NO_ERROR;
         } break;
-        case CREATE_OMX: {
+        case GET_OMX: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
-            sp<IOMX> omx = createOMX();
+            sp<IOMX> omx = getOMX();
             reply->writeStrongBinder(omx->asBinder());
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index e74f1a9..76a9e7d 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -24,7 +24,6 @@
     ALLOC_BUFFER,
     ALLOC_BUFFER_WITH_BACKUP,
     FREE_BUFFER,
-    OBSERVE_NODE,
     FILL_BUFFER,
     EMPTY_BUFFER,
     GET_EXTENSION_INDEX,
@@ -76,7 +75,7 @@
         : BpInterface<IOMX>(impl) {
     }
 
-    virtual status_t list_nodes(List<String8> *list) {
+    virtual status_t listNodes(List<String8> *list) {
         list->clear();
 
         Parcel data, reply;
@@ -93,10 +92,12 @@
         return OK;
     }
 
-    virtual status_t allocate_node(const char *name, node_id *node) {
+    virtual status_t allocateNode(
+            const char *name, const sp<IOMXObserver> &observer, node_id *node) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeCString(name);
+        data.writeStrongBinder(observer->asBinder());
         remote()->transact(ALLOCATE_NODE, data, &reply);
 
         status_t err = reply.readInt32();
@@ -109,7 +110,7 @@
         return err;
     }
 
-    virtual status_t free_node(node_id node) {
+    virtual status_t freeNode(node_id node) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
@@ -118,7 +119,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t send_command(
+    virtual status_t sendCommand(
             node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
@@ -130,7 +131,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t get_parameter(
+    virtual status_t getParameter(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size) {
         Parcel data, reply;
@@ -151,7 +152,7 @@
         return OK;
     }
 
-    virtual status_t set_parameter(
+    virtual status_t setParameter(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size) {
         Parcel data, reply;
@@ -165,7 +166,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t get_config(
+    virtual status_t getConfig(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size) {
         Parcel data, reply;
@@ -186,7 +187,7 @@
         return OK;
     }
 
-    virtual status_t set_config(
+    virtual status_t setConfig(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size) {
         Parcel data, reply;
@@ -200,7 +201,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t use_buffer(
+    virtual status_t useBuffer(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer) {
         Parcel data, reply;
@@ -222,7 +223,7 @@
         return err;
     }
 
-    virtual status_t allocate_buffer(
+    virtual status_t allocateBuffer(
             node_id node, OMX_U32 port_index, size_t size,
             buffer_id *buffer) {
         Parcel data, reply;
@@ -244,7 +245,7 @@
         return err;
     }
 
-    virtual status_t allocate_buffer_with_backup(
+    virtual status_t allocateBufferWithBackup(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer) {
         Parcel data, reply;
@@ -266,7 +267,7 @@
         return err;
     }
 
-    virtual status_t free_buffer(
+    virtual status_t freeBuffer(
             node_id node, OMX_U32 port_index, buffer_id buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
@@ -278,18 +279,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t observe_node(
-            node_id node, const sp<IOMXObserver> &observer) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeIntPtr((intptr_t)node);
-        data.writeStrongBinder(observer->asBinder());
-        remote()->transact(OBSERVE_NODE, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t fill_buffer(node_id node, buffer_id buffer) {
+    virtual status_t fillBuffer(node_id node, buffer_id buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
@@ -299,7 +289,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t empty_buffer(
+    virtual status_t emptyBuffer(
             node_id node,
             buffer_id buffer,
             OMX_U32 range_offset, OMX_U32 range_length,
@@ -317,7 +307,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t get_extension_index(
+    virtual status_t getExtensionIndex(
             node_id node,
             const char *parameter_name,
             OMX_INDEXTYPE *index) {
@@ -379,7 +369,7 @@
             CHECK_INTERFACE(IOMX, data, reply);
 
             List<String8> list;
-            list_nodes(&list);
+            listNodes(&list);
 
             reply->writeInt32(list.size());
             for (List<String8>::iterator it = list.begin();
@@ -394,8 +384,14 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
+            const char *name = data.readCString();
+
+            sp<IOMXObserver> observer =
+                interface_cast<IOMXObserver>(data.readStrongBinder());
+
             node_id node;
-            status_t err = allocate_node(data.readCString(), &node);
+
+            status_t err = allocateNode(name, observer, &node);
             reply->writeInt32(err);
             if (err == OK) {
                 reply->writeIntPtr((intptr_t)node);
@@ -410,7 +406,7 @@
 
             node_id node = (void*)data.readIntPtr();
 
-            reply->writeInt32(free_node(node));
+            reply->writeInt32(freeNode(node));
                 
             return NO_ERROR;
         }
@@ -425,7 +421,7 @@
                 static_cast<OMX_COMMANDTYPE>(data.readInt32());
 
             OMX_S32 param = data.readInt32();
-            reply->writeInt32(send_command(node, cmd, param));
+            reply->writeInt32(sendCommand(node, cmd, param));
 
             return NO_ERROR;
         }
@@ -443,7 +439,7 @@
             void *params = malloc(size);
             data.read(params, size);
 
-            status_t err = get_parameter(node, index, params, size);
+            status_t err = getParameter(node, index, params, size);
 
             reply->writeInt32(err);
 
@@ -467,7 +463,7 @@
             size_t size = data.readInt32();
             void *params = const_cast<void *>(data.readInplace(size));
 
-            reply->writeInt32(set_parameter(node, index, params, size));
+            reply->writeInt32(setParameter(node, index, params, size));
 
             return NO_ERROR;
         }
@@ -485,7 +481,7 @@
             void *params = malloc(size);
             data.read(params, size);
 
-            status_t err = get_config(node, index, params, size);
+            status_t err = getConfig(node, index, params, size);
 
             reply->writeInt32(err);
 
@@ -509,7 +505,7 @@
             size_t size = data.readInt32();
             void *params = const_cast<void *>(data.readInplace(size));
 
-            reply->writeInt32(set_config(node, index, params, size));
+            reply->writeInt32(setConfig(node, index, params, size));
 
             return NO_ERROR;
         }
@@ -524,7 +520,7 @@
                 interface_cast<IMemory>(data.readStrongBinder());
 
             buffer_id buffer;
-            status_t err = use_buffer(node, port_index, params, &buffer);
+            status_t err = useBuffer(node, port_index, params, &buffer);
             reply->writeInt32(err);
 
             if (err == OK) {
@@ -543,7 +539,7 @@
             size_t size = data.readInt32();
 
             buffer_id buffer;
-            status_t err = allocate_buffer(node, port_index, size, &buffer);
+            status_t err = allocateBuffer(node, port_index, size, &buffer);
             reply->writeInt32(err);
 
             if (err == OK) {
@@ -563,7 +559,7 @@
                 interface_cast<IMemory>(data.readStrongBinder());
 
             buffer_id buffer;
-            status_t err = allocate_buffer_with_backup(
+            status_t err = allocateBufferWithBackup(
                     node, port_index, params, &buffer);
 
             reply->writeInt32(err);
@@ -582,19 +578,7 @@
             node_id node = (void*)data.readIntPtr();
             OMX_U32 port_index = data.readInt32();
             buffer_id buffer = (void*)data.readIntPtr();
-            reply->writeInt32(free_buffer(node, port_index, buffer));
-
-            return NO_ERROR;
-        }
-
-        case OBSERVE_NODE:
-        {
-            CHECK_INTERFACE(IOMX, data, reply);
-
-            node_id node = (void*)data.readIntPtr();
-            sp<IOMXObserver> observer =
-                interface_cast<IOMXObserver>(data.readStrongBinder());
-            reply->writeInt32(observe_node(node, observer));
+            reply->writeInt32(freeBuffer(node, port_index, buffer));
 
             return NO_ERROR;
         }
@@ -605,7 +589,7 @@
 
             node_id node = (void*)data.readIntPtr();
             buffer_id buffer = (void*)data.readIntPtr();
-            reply->writeInt32(fill_buffer(node, buffer));
+            reply->writeInt32(fillBuffer(node, buffer));
 
             return NO_ERROR;
         }
@@ -622,7 +606,7 @@
             OMX_TICKS timestamp = data.readInt64();
 
             reply->writeInt32(
-                    empty_buffer(
+                    emptyBuffer(
                         node, buffer, range_offset, range_length,
                         flags, timestamp));
 
@@ -637,7 +621,7 @@
             const char *parameter_name = data.readCString();
             
             OMX_INDEXTYPE index;
-            status_t err = get_extension_index(node, parameter_name, &index);
+            status_t err = getExtensionIndex(node, parameter_name, &index);
 
             reply->writeInt32(err);
 
@@ -688,7 +672,7 @@
         : BpInterface<IOMXObserver>(impl) {
     }
 
-    virtual void on_message(const omx_message &msg) {
+    virtual void onMessage(const omx_message &msg) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
         data.write(&msg, sizeof(msg));
@@ -710,7 +694,7 @@
             data.read(&msg, sizeof(msg));
 
             // XXX Could use readInplace maybe?
-            on_message(msg);
+            onMessage(msg);
 
             return NO_ERROR;
         }
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index ef41225..6fc9fa2 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -51,7 +51,7 @@
 	$(JNI_H_INCLUDE)                                                \
 	$(call include-path-for, graphics corecg)                       \
 	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
-	$(TOP)/frameworks/base/media/libstagefright/omx
+	$(TOP)/frameworks/base/media/libstagefright/include
 
 LOCAL_MODULE:= libmediaplayerservice
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 84be874..ab759df 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -274,8 +274,14 @@
     return c;
 }
 
-sp<IOMX> MediaPlayerService::createOMX() {
-    return new OMX;
+sp<IOMX> MediaPlayerService::getOMX() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mOMX.get() == NULL) {
+        mOMX = new OMX;
+    }
+
+    return mOMX;
 }
 
 status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 7d2e611..931667e 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -183,7 +183,7 @@
     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
     virtual sp<IMemory>         snoop();
-    virtual sp<IOMX>            createOMX();
+    virtual sp<IOMX>            getOMX();
 
     virtual status_t            dump(int fd, const Vector<String16>& args);
 
@@ -281,6 +281,7 @@
     mutable     Mutex                       mLock;
                 SortedVector< wp<Client> >  mClients;
                 int32_t                     mNextConnId;
+                sp<IOMX>                    mOMX;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index fa92024..cc25886 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "include/string.h"
+#include "include/stagefright_string.h"
 #include "include/HTTPStream.h"
 
 #include <stdlib.h>
diff --git a/media/libstagefright/MediaPlayerImpl.cpp b/media/libstagefright/MediaPlayerImpl.cpp
index 3747a8d..4e0e996 100644
--- a/media/libstagefright/MediaPlayerImpl.cpp
+++ b/media/libstagefright/MediaPlayerImpl.cpp
@@ -18,7 +18,7 @@
 #define LOG_TAG "MediaPlayerImpl"
 #include "utils/Log.h"
 
-#include "include/string.h"
+#include "include/stagefright_string.h"
 #include "include/HTTPStream.h"
 
 #include <OMX_Component.h>
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index dba7a2a..9de873e 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -35,7 +35,7 @@
 
     CHECK(service.get() != NULL);
 
-    mOMX = service->createOMX();
+    mOMX = service->getOMX();
     CHECK(mOMX.get() != NULL);
 
     return OK;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 5201c5a..264271d 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -88,12 +88,15 @@
 #define CODEC_LOGV(x, ...) LOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
 
 struct OMXCodecObserver : public BnOMXObserver {
-    OMXCodecObserver(const wp<OMXCodec> &target)
-        : mTarget(target) {
+    OMXCodecObserver() {
+    }
+
+    void setCodec(const sp<OMXCodec> &target) {
+        mTarget = target;
     }
 
     // from IOMXObserver
-    virtual void on_message(const omx_message &msg) {
+    virtual void onMessage(const omx_message &msg) {
         sp<OMXCodec> codec = mTarget.promote();
 
         if (codec.get() != NULL) {
@@ -180,6 +183,7 @@
     CHECK(success);
 
     const char *componentName = NULL;
+    sp<OMXCodecObserver> observer = new OMXCodecObserver;
     IOMX::node_id node = 0;
     for (int index = 0;; ++index) {
         if (createEncoder) {
@@ -203,7 +207,7 @@
 
         LOGV("Attempting to allocate OMX node '%s'", componentName);
 
-        status_t err = omx->allocate_node(componentName, &node);
+        status_t err = omx->allocateNode(componentName, observer, &node);
         if (err == OK) {
             LOGV("Successfully allocated OMX node '%s'", componentName);
             break;
@@ -245,6 +249,8 @@
             omx, node, quirks, createEncoder, mime, componentName,
             source);
 
+    observer->setCodec(codec);
+
     uint32_t type;
     const void *data;
     size_t size;
@@ -325,15 +331,15 @@
         LOGV("AVC profile = %d (%s), level = %d",
              (int)profile, AVCProfileToString(profile), (int)level / 10);
 
-#if 0
         if (!strcmp(componentName, "OMX.TI.Video.Decoder")
             && (profile != kAVCProfileBaseline || level > 39)) {
-            // This stream exceeds the decoder's capabilities.
+            // This stream exceeds the decoder's capabilities. The decoder
+            // does not handle this gracefully and would clobber the heap
+            // and wreak havoc instead...
 
             LOGE("Profile and/or level exceed the decoder's capabilities.");
             return NULL;
         }
-#endif
     }
 
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
@@ -404,7 +410,7 @@
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -413,7 +419,7 @@
 
     }
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 }
@@ -431,7 +437,7 @@
     OMX_U32 index = 0;
     for (;;) {
         format.nIndex = index;
-        status_t err = mOMX->get_parameter(
+        status_t err = mOMX->getParameter(
                 mNode, OMX_IndexParamVideoPortFormat,
                 &format, sizeof(format));
 
@@ -477,7 +483,7 @@
     }
 
     CODEC_LOGV("found a match.");
-    status_t err = mOMX->set_parameter(
+    status_t err = mOMX->setParameter(
             mNode, OMX_IndexParamVideoPortFormat,
             &format, sizeof(format));
 
@@ -520,7 +526,7 @@
 
     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     CHECK_EQ(err, OK);
@@ -532,7 +538,7 @@
     video_def->eCompressionFormat = compressionFormat;
     video_def->eColorFormat = OMX_COLOR_FormatUnused;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -541,7 +547,7 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexInput;
 
-    err = mOMX->get_parameter(
+    err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -555,7 +561,7 @@
     video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
     video_def->eColorFormat = colorFormat;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 }
@@ -586,7 +592,7 @@
         format.nPortIndex = kPortIndexOutput;
         format.nIndex = 0;
 
-        status_t err = mOMX->get_parameter(
+        status_t err = mOMX->getParameter(
                 mNode, OMX_IndexParamVideoPortFormat,
                 &format, sizeof(format));
         CHECK_EQ(err, OK);
@@ -599,7 +605,7 @@
                || format.eColorFormat == OMX_COLOR_FormatCbYCrY
                || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
 
-        err = mOMX->set_parameter(
+        err = mOMX->setParameter(
                 mNode, OMX_IndexParamVideoPortFormat,
                 &format, sizeof(format));
         CHECK_EQ(err, OK);
@@ -612,7 +618,7 @@
 
     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     CHECK_EQ(err, OK);
@@ -632,7 +638,7 @@
 
     video_def->eColorFormat = OMX_COLOR_FormatUnused;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -641,7 +647,7 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
 
-    err = mOMX->get_parameter(
+    err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
     CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
@@ -654,7 +660,7 @@
     video_def->nFrameWidth = width;
     video_def->nFrameHeight = height;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 }
@@ -683,9 +689,6 @@
     mPortStatus[kPortIndexInput] = ENABLED;
     mPortStatus[kPortIndexOutput] = ENABLED;
 
-    mObserver = new OMXCodecObserver(this);
-    mOMX->observe_node(mNode, mObserver);
-
     setComponentRole();
 }
 
@@ -743,7 +746,7 @@
 
         roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
 
-        status_t err = omx->set_parameter(
+        status_t err = omx->setParameter(
                 node, OMX_IndexParamStandardComponentRole,
                 &roleParams, sizeof(roleParams));
 
@@ -760,10 +763,7 @@
 OMXCodec::~OMXCodec() {
     CHECK(mState == LOADED || mState == ERROR);
 
-    status_t err = mOMX->observe_node(mNode, NULL);
-    CHECK_EQ(err, OK);
-
-    err = mOMX->free_node(mNode);
+    status_t err = mOMX->freeNode(mNode);
     CHECK_EQ(err, OK);
 
     mNode = NULL;
@@ -785,7 +785,7 @@
 
     status_t err;
     if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
-        err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+        err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
         CHECK_EQ(err, OK);
         setState(LOADED_TO_IDLE);
     }
@@ -794,7 +794,7 @@
     CHECK_EQ(err, OK);
 
     if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
-        err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+        err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
         CHECK_EQ(err, OK);
 
         setState(LOADED_TO_IDLE);
@@ -831,7 +831,7 @@
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err != OK) {
@@ -848,14 +848,14 @@
         IOMX::buffer_id buffer;
         if (portIndex == kPortIndexInput
                 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
-            err = mOMX->allocate_buffer_with_backup(
+            err = mOMX->allocateBufferWithBackup(
                     mNode, portIndex, mem, &buffer);
         } else if (portIndex == kPortIndexOutput
                 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
-            err = mOMX->allocate_buffer_with_backup(
+            err = mOMX->allocateBufferWithBackup(
                     mNode, portIndex, mem, &buffer);
         } else {
-            err = mOMX->use_buffer(mNode, portIndex, mem, &buffer);
+            err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
         }
 
         if (err != OK) {
@@ -922,7 +922,7 @@
                 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
 
                 status_t err =
-                    mOMX->free_buffer(mNode, kPortIndexInput, buffer);
+                    mOMX->freeBuffer(mNode, kPortIndexInput, buffer);
                 CHECK_EQ(err, OK);
 
                 buffers->removeAt(i);
@@ -968,7 +968,7 @@
                 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
 
                 status_t err =
-                    mOMX->free_buffer(mNode, kPortIndexOutput, buffer);
+                    mOMX->freeBuffer(mNode, kPortIndexOutput, buffer);
                 CHECK_EQ(err, OK);
 
                 buffers->removeAt(i);
@@ -1058,6 +1058,71 @@
     }
 }
 
+// Has the format changed in any way that the client would have to be aware of?
+static bool formatHasNotablyChanged(
+        const sp<MetaData> &from, const sp<MetaData> &to) {
+    if (from.get() == NULL && to.get() == NULL) {
+        return false;
+    }
+
+    if (from.get() == NULL && to.get() != NULL
+        || from.get() != NULL && to.get() == NULL) {
+        return true;
+    }
+
+    const char *mime_from, *mime_to;
+    CHECK(from->findCString(kKeyMIMEType, &mime_from));
+    CHECK(to->findCString(kKeyMIMEType, &mime_to));
+
+    if (strcasecmp(mime_from, mime_to)) {
+        return true;
+    }
+
+    if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) {
+        int32_t colorFormat_from, colorFormat_to;
+        CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from));
+        CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to));
+
+        if (colorFormat_from != colorFormat_to) {
+            return true;
+        }
+
+        int32_t width_from, width_to;
+        CHECK(from->findInt32(kKeyWidth, &width_from));
+        CHECK(to->findInt32(kKeyWidth, &width_to));
+
+        if (width_from != width_to) {
+            return true;
+        }
+
+        int32_t height_from, height_to;
+        CHECK(from->findInt32(kKeyHeight, &height_from));
+        CHECK(to->findInt32(kKeyHeight, &height_to));
+
+        if (height_from != height_to) {
+            return true;
+        }
+    } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) {
+        int32_t numChannels_from, numChannels_to;
+        CHECK(from->findInt32(kKeyChannelCount, &numChannels_from));
+        CHECK(to->findInt32(kKeyChannelCount, &numChannels_to));
+
+        if (numChannels_from != numChannels_to) {
+            return true;
+        }
+
+        int32_t sampleRate_from, sampleRate_to;
+        CHECK(from->findInt32(kKeySampleRate, &sampleRate_from));
+        CHECK(to->findInt32(kKeySampleRate, &sampleRate_to));
+
+        if (sampleRate_from != sampleRate_to) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
     switch (cmd) {
         case OMX_CommandStateSet:
@@ -1080,8 +1145,14 @@
             if (mState == RECONFIGURING) {
                 CHECK_EQ(portIndex, kPortIndexOutput);
 
+                sp<MetaData> oldOutputFormat = mOutputFormat;
                 initOutputFormat(mSource->getFormat());
-                mOutputPortSettingsHaveChanged = true;
+
+                // Don't notify clients if the output port settings change
+                // wasn't of importance to them, i.e. it may be that just the
+                // number of buffers has changed and nothing else.
+                mOutputPortSettingsHaveChanged =
+                    formatHasNotablyChanged(oldOutputFormat, mOutputFormat);
 
                 enablePortAsync(portIndex);
 
@@ -1137,7 +1208,7 @@
                     mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
 
                     status_t err =
-                        mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+                        mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
                     CHECK_EQ(err, OK);
                 }
             } else {
@@ -1177,7 +1248,7 @@
         {
             CODEC_LOGV("Now Idle.");
             if (mState == LOADED_TO_IDLE) {
-                status_t err = mOMX->send_command(
+                status_t err = mOMX->sendCommand(
                         mNode, OMX_CommandStateSet, OMX_StateExecuting);
 
                 CHECK_EQ(err, OK);
@@ -1194,7 +1265,7 @@
                     countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
                     mPortBuffers[kPortIndexOutput].size());
 
-                status_t err = mOMX->send_command(
+                status_t err = mOMX->sendCommand(
                         mNode, OMX_CommandStateSet, OMX_StateLoaded);
 
                 CHECK_EQ(err, OK);
@@ -1277,7 +1348,7 @@
         CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
 
         status_t err =
-            mOMX->free_buffer(mNode, portIndex, info->mBuffer);
+            mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
 
         if (err != OK) {
             stickyErr = err;
@@ -1337,7 +1408,7 @@
     }
 
     status_t err =
-        mOMX->send_command(mNode, OMX_CommandFlush, portIndex);
+        mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
     CHECK_EQ(err, OK);
 
     return true;
@@ -1350,7 +1421,7 @@
     mPortStatus[portIndex] = DISABLING;
 
     status_t err =
-        mOMX->send_command(mNode, OMX_CommandPortDisable, portIndex);
+        mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
     CHECK_EQ(err, OK);
 
     freeBuffersOnPort(portIndex, true);
@@ -1363,7 +1434,7 @@
     mPortStatus[portIndex] = ENABLING;
 
     status_t err =
-        mOMX->send_command(mNode, OMX_CommandPortEnable, portIndex);
+        mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
     CHECK_EQ(err, OK);
 }
 
@@ -1415,7 +1486,7 @@
             memcpy(info->mMem->pointer(), specific->mData, specific->mSize);
         }
 
-        status_t err = mOMX->empty_buffer(
+        status_t err = mOMX->emptyBuffer(
                 mNode, info->mBuffer, 0, size,
                 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
                 0);
@@ -1461,9 +1532,9 @@
                srcLength);
 
         if (srcBuffer->meta_data()->findInt64(kKeyTime, &timestampUs)) {
-            CODEC_LOGV("Calling empty_buffer on buffer %p (length %d)",
+            CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d)",
                  info->mBuffer, srcLength);
-            CODEC_LOGV("Calling empty_buffer with timestamp %lld us (%.2f secs)",
+            CODEC_LOGV("Calling emptyBuffer with timestamp %lld us (%.2f secs)",
                  timestampUs, timestampUs / 1E6);
         }
     }
@@ -1473,7 +1544,7 @@
         srcBuffer = NULL;
     }
 
-    err = mOMX->empty_buffer(
+    err = mOMX->emptyBuffer(
             mNode, info->mBuffer, 0, srcLength,
             flags, timestampUs);
 
@@ -1495,7 +1566,7 @@
     }
 
     CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
-    status_t err = mOMX->fill_buffer(mNode, info->mBuffer);
+    status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
     CHECK_EQ(err, OK);
 
     info->mOwnedByComponent = true;
@@ -1540,7 +1611,7 @@
     InitOMXParams(&pcmParams);
     pcmParams.nPortIndex = portIndex;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
 
     CHECK_EQ(err, OK);
@@ -1561,7 +1632,7 @@
         pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
     }
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
 
     CHECK_EQ(err, OK);
@@ -1574,14 +1645,14 @@
         def.nPortIndex = kPortIndexInput;
 
         status_t err =
-            mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+            mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
 
         CHECK_EQ(err, OK);
 
         def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
         def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
 
-        err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+        err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
         CHECK_EQ(err, OK);
     }
 
@@ -1605,14 +1676,14 @@
         def.nPortIndex = kPortIndexInput;
 
         status_t err =
-            mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+            mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
 
         CHECK_EQ(err, OK);
 
         def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
         def.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
 
-        err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+        err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
         CHECK_EQ(err, OK);
     }
 
@@ -1637,7 +1708,7 @@
         InitOMXParams(&profile);
         profile.nPortIndex = kPortIndexInput;
 
-        status_t err = mOMX->get_parameter(
+        status_t err = mOMX->getParameter(
                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
         CHECK_EQ(err, OK);
 
@@ -1645,7 +1716,7 @@
         profile.nSampleRate = sampleRate;
         profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
 
-        err = mOMX->set_parameter(
+        err = mOMX->setParameter(
                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
         CHECK_EQ(err, OK);
     }
@@ -1669,7 +1740,7 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -1718,7 +1789,7 @@
 
     def.nBufferCountActual = def.nBufferCountMin;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 }
@@ -1729,7 +1800,7 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexInput;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -1743,7 +1814,7 @@
     def.nBufferSize = compressedSize;
     def.nBufferCountActual = def.nBufferCountMin;
 
-    err = mOMX->set_parameter(
+    err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 }
@@ -1834,7 +1905,7 @@
                 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
 
                 status_t err =
-                    mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+                    mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
                 CHECK_EQ(err, OK);
             }
 
@@ -2172,7 +2243,7 @@
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -2238,7 +2309,7 @@
                 InitOMXParams(&params);
                 params.nPortIndex = portIndex;
 
-                err = mOMX->get_parameter(
+                err = mOMX->getParameter(
                         mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
                 CHECK_EQ(err, OK);
 
@@ -2257,7 +2328,7 @@
                 InitOMXParams(&amr);
                 amr.nPortIndex = portIndex;
 
-                err = mOMX->get_parameter(
+                err = mOMX->getParameter(
                         mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
                 CHECK_EQ(err, OK);
 
@@ -2289,7 +2360,7 @@
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
 
-    status_t err = mOMX->get_parameter(
+    status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -2315,7 +2386,7 @@
                 InitOMXParams(&params);
                 params.nPortIndex = kPortIndexOutput;
 
-                err = mOMX->get_parameter(
+                err = mOMX->getParameter(
                         mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
                 CHECK_EQ(err, OK);
 
@@ -2347,7 +2418,7 @@
                 InitOMXParams(&amr);
                 amr.nPortIndex = kPortIndexOutput;
 
-                err = mOMX->get_parameter(
+                err = mOMX->getParameter(
                         mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
                 CHECK_EQ(err, OK);
 
@@ -2444,8 +2515,9 @@
             return OK;
         }
 
+        sp<OMXCodecObserver> observer = new OMXCodecObserver;
         IOMX::node_id node;
-        status_t err = omx->allocate_node(componentName, &node);
+        status_t err = omx->allocateNode(componentName, observer, &node);
 
         if (err != OK) {
             continue;
@@ -2463,7 +2535,7 @@
         param.nPortIndex = queryDecoders ? 0 : 1;
 
         for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
-            err = omx->get_parameter(
+            err = omx->getParameter(
                     node, OMX_IndexParamVideoProfileLevelQuerySupported,
                     &param, sizeof(param));
 
@@ -2478,7 +2550,7 @@
             caps->mProfileLevels.push(profileLevel);
         }
 
-        CHECK_EQ(omx->free_node(node), OK);
+        CHECK_EQ(omx->freeNode(node), OK);
     }
 }
 
diff --git a/media/libstagefright/ShoutcastSource.cpp b/media/libstagefright/ShoutcastSource.cpp
index d420e6b..ec25430 100644
--- a/media/libstagefright/ShoutcastSource.cpp
+++ b/media/libstagefright/ShoutcastSource.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "include/string.h"
+#include "include/stagefright_string.h"
 #include "include/HTTPStream.h"
 
 #include <stdlib.h>
diff --git a/media/libstagefright/include/HTTPStream.h b/media/libstagefright/include/HTTPStream.h
index e05d911..43ef614 100644
--- a/media/libstagefright/include/HTTPStream.h
+++ b/media/libstagefright/include/HTTPStream.h
@@ -18,7 +18,7 @@
 
 #define HTTP_STREAM_H_
 
-#include "string.h"
+#include "stagefright_string.h"
 
 #include <sys/types.h>
 
diff --git a/media/libstagefright/omx/OMX.h b/media/libstagefright/include/OMX.h
similarity index 61%
rename from media/libstagefright/omx/OMX.h
rename to media/libstagefright/include/OMX.h
index 4c14dd9..a4b62b2 100644
--- a/media/libstagefright/omx/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -19,66 +19,67 @@
 
 #include <media/IOMX.h>
 #include <utils/threads.h>
+#include <utils/KeyedVector.h>
 
 namespace android {
 
-class NodeMeta;
+class OMXNodeInstance;
 
-class OMX : public BnOMX {
+class OMX : public BnOMX,
+            public IBinder::DeathRecipient {
 public:
     OMX();
 
-    virtual status_t list_nodes(List<String8> *list);
+    virtual status_t listNodes(List<String8> *list);
 
-    virtual status_t allocate_node(const char *name, node_id *node);
-    virtual status_t free_node(node_id node);
+    virtual status_t allocateNode(
+            const char *name, const sp<IOMXObserver> &observer, node_id *node);
 
-    virtual status_t send_command(
+    virtual status_t freeNode(node_id node);
+
+    virtual status_t sendCommand(
             node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
 
-    virtual status_t get_parameter(
+    virtual status_t getParameter(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size);
 
-    virtual status_t set_parameter(
+    virtual status_t setParameter(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size);
 
-    virtual status_t get_config(
+    virtual status_t getConfig(
             node_id node, OMX_INDEXTYPE index,
             void *params, size_t size);
 
-    virtual status_t set_config(
+    virtual status_t setConfig(
             node_id node, OMX_INDEXTYPE index,
             const void *params, size_t size);
 
-    virtual status_t use_buffer(
+    virtual status_t useBuffer(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer);
 
-    virtual status_t allocate_buffer(
+    virtual status_t allocateBuffer(
             node_id node, OMX_U32 port_index, size_t size,
             buffer_id *buffer);
 
-    virtual status_t allocate_buffer_with_backup(
+    virtual status_t allocateBufferWithBackup(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer);
 
-    virtual status_t free_buffer(
+    virtual status_t freeBuffer(
             node_id node, OMX_U32 port_index, buffer_id buffer);
 
-    virtual status_t observe_node(
-            node_id node, const sp<IOMXObserver> &observer);
+    virtual status_t fillBuffer(node_id node, buffer_id buffer);
 
-    virtual status_t fill_buffer(node_id node, buffer_id buffer);
-
-    virtual status_t empty_buffer(
+    virtual status_t emptyBuffer(
             node_id node,
             buffer_id buffer,
             OMX_U32 range_offset, OMX_U32 range_length,
             OMX_U32 flags, OMX_TICKS timestamp);
 
-    virtual status_t get_extension_index(
+    virtual status_t getExtensionIndex(
             node_id node,
             const char *parameter_name,
             OMX_INDEXTYPE *index);
@@ -90,44 +91,38 @@
             size_t encodedWidth, size_t encodedHeight,
             size_t displayWidth, size_t displayHeight);
 
-private:
-    static OMX_CALLBACKTYPE kCallbacks;
-
-    Mutex mLock;
-
-    struct CallbackDispatcher;
-    sp<CallbackDispatcher> mDispatcher;
-
-    static OMX_ERRORTYPE OnEvent(
-            OMX_IN OMX_HANDLETYPE hComponent,
-            OMX_IN OMX_PTR pAppData,
-            OMX_IN OMX_EVENTTYPE eEvent,
-            OMX_IN OMX_U32 nData1,
-            OMX_IN OMX_U32 nData2,
-            OMX_IN OMX_PTR pEventData);
-
-    static OMX_ERRORTYPE OnEmptyBufferDone(
-            OMX_IN OMX_HANDLETYPE hComponent,
-            OMX_IN OMX_PTR pAppData,
-            OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
-
-    static OMX_ERRORTYPE OnFillBufferDone(
-            OMX_IN OMX_HANDLETYPE hComponent,
-            OMX_IN OMX_PTR pAppData,
-            OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+    virtual void binderDied(const wp<IBinder> &the_late_who);
 
     OMX_ERRORTYPE OnEvent(
-            NodeMeta *meta,
+            node_id node,
             OMX_IN OMX_EVENTTYPE eEvent,
             OMX_IN OMX_U32 nData1,
             OMX_IN OMX_U32 nData2,
             OMX_IN OMX_PTR pEventData);
         
     OMX_ERRORTYPE OnEmptyBufferDone(
-            NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+            node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
 
     OMX_ERRORTYPE OnFillBufferDone(
-            NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+            node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+
+    void invalidateNodeID(node_id node);
+
+private:
+    Mutex mLock;
+
+    struct CallbackDispatcher;
+    sp<CallbackDispatcher> mDispatcher;
+
+    int32_t mNodeCounter;
+
+    KeyedVector<wp<IBinder>, OMXNodeInstance *> mLiveNodes;
+    KeyedVector<node_id, OMXNodeInstance *> mNodeIDToInstance;
+
+    node_id makeNodeID(OMXNodeInstance *instance);
+    OMXNodeInstance *findInstance(node_id node);
+
+    void invalidateNodeID_l(node_id node);
 
     OMX(const OMX &);
     OMX &operator=(const OMX &);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
new file mode 100644
index 0000000..181742e
--- /dev/null
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -0,0 +1,115 @@
+/*
+ * 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 OMX_NODE_INSTANCE_H_
+
+#define OMX_NODE_INSTANCE_H_
+
+#include "OMX.h"
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class IOMXObserver;
+
+struct OMXNodeInstance {
+    OMXNodeInstance(
+            OMX *owner, const sp<IOMXObserver> &observer);
+
+    void setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle);
+
+    OMX *owner();
+    sp<IOMXObserver> observer();
+    OMX::node_id nodeID();
+
+    status_t freeNode();
+
+    status_t sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param);
+    status_t getParameter(OMX_INDEXTYPE index, void *params, size_t size);
+
+    status_t setParameter(
+            OMX_INDEXTYPE index, const void *params, size_t size);
+
+    status_t getConfig(OMX_INDEXTYPE index, void *params, size_t size);
+    status_t setConfig(OMX_INDEXTYPE index, const void *params, size_t size);
+
+    status_t useBuffer(
+            OMX_U32 portIndex, const sp<IMemory> &params,
+            OMX::buffer_id *buffer);
+
+    status_t allocateBuffer(
+            OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer);
+
+    status_t allocateBufferWithBackup(
+            OMX_U32 portIndex, const sp<IMemory> &params,
+            OMX::buffer_id *buffer);
+
+    status_t freeBuffer(OMX_U32 portIndex, OMX::buffer_id buffer);
+
+    status_t fillBuffer(OMX::buffer_id buffer);
+
+    status_t emptyBuffer(
+            OMX::buffer_id buffer,
+            OMX_U32 rangeOffset, OMX_U32 rangeLength,
+            OMX_U32 flags, OMX_TICKS timestamp);
+
+    status_t getExtensionIndex(
+            const char *parameterName, OMX_INDEXTYPE *index);
+
+    void onMessage(const omx_message &msg);
+    void onObserverDied();
+    void onGetHandleFailed();
+
+    static OMX_CALLBACKTYPE kCallbacks;
+
+private:
+    Mutex mLock;
+
+    OMX *mOwner;
+    OMX::node_id mNodeID;
+    OMX_HANDLETYPE mHandle;
+    sp<IOMXObserver> mObserver;
+
+    ~OMXNodeInstance();
+
+    static OMX_ERRORTYPE OnEvent(
+            OMX_IN OMX_HANDLETYPE hComponent,
+            OMX_IN OMX_PTR pAppData,
+            OMX_IN OMX_EVENTTYPE eEvent,
+            OMX_IN OMX_U32 nData1,
+            OMX_IN OMX_U32 nData2,
+            OMX_IN OMX_PTR pEventData);
+
+    static OMX_ERRORTYPE OnEmptyBufferDone(
+            OMX_IN OMX_HANDLETYPE hComponent,
+            OMX_IN OMX_PTR pAppData,
+            OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+
+    static OMX_ERRORTYPE OnFillBufferDone(
+            OMX_IN OMX_HANDLETYPE hComponent,
+            OMX_IN OMX_PTR pAppData,
+            OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+
+    OMXNodeInstance(const OMXNodeInstance &);
+    OMXNodeInstance &operator=(const OMXNodeInstance &);
+};
+
+}  // namespace android
+
+#endif  // OMX_NODE_INSTANCE_H_
+
diff --git a/media/libstagefright/include/string.h b/media/libstagefright/include/stagefright_string.h
similarity index 100%
rename from media/libstagefright/include/string.h
rename to media/libstagefright/include/stagefright_string.h
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 468221e..edbc04e 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -12,6 +12,7 @@
 LOCAL_SRC_FILES:=                 \
         ColorConverter.cpp        \
 	OMX.cpp                   \
+        OMXNodeInstance.cpp       \
         QComHardwareRenderer.cpp  \
         SoftwareRenderer.cpp      \
         TIHardwareRenderer.cpp
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 8d100d9..3800a26 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -18,13 +18,12 @@
 #define LOG_TAG "OMX"
 #include <utils/Log.h>
 
-#include <sys/socket.h>
-
-#include "OMX.h"
+#include "../include/OMX.h"
 #include "OMXRenderer.h"
 
 #include "pv_omxcore.h"
 
+#include "../include/OMXNodeInstance.h"
 #include "../include/QComHardwareRenderer.h"
 #include "../include/SoftwareRenderer.h"
 #include "../include/TIHardwareRenderer.h"
@@ -37,47 +36,10 @@
 
 namespace android {
 
-class NodeMeta {
-public:
-    NodeMeta(OMX *owner)
-        : mOwner(owner),
-          mHandle(NULL) {
-    }
-
-    OMX *owner() const {
-        return mOwner;
-    }
-
-    void setHandle(OMX_HANDLETYPE handle) {
-        CHECK_EQ(mHandle, NULL);
-        mHandle = handle;
-    }
-
-    OMX_HANDLETYPE handle() const {
-        return mHandle;
-    }
-
-    void setObserver(const sp<IOMXObserver> &observer) {
-        mObserver = observer;
-    }
-
-    sp<IOMXObserver> observer() {
-        return mObserver;
-    }
-
-private:
-    OMX *mOwner;
-    OMX_HANDLETYPE mHandle;
-    sp<IOMXObserver> mObserver;
-
-    NodeMeta(const NodeMeta &);
-    NodeMeta &operator=(const NodeMeta &);
-};
-
 ////////////////////////////////////////////////////////////////////////////////
 
 struct OMX::CallbackDispatcher : public RefBase {
-    CallbackDispatcher();
+    CallbackDispatcher(OMX *owner);
 
     void post(const omx_message &msg);
 
@@ -86,6 +48,8 @@
 
 private:
     Mutex mLock;
+
+    OMX *mOwner;
     bool mDone;
     Condition mQueueChanged;
     List<omx_message> mQueue;
@@ -101,8 +65,9 @@
     CallbackDispatcher &operator=(const CallbackDispatcher &);
 };
 
-OMX::CallbackDispatcher::CallbackDispatcher()
-    : mDone(false) {
+OMX::CallbackDispatcher::CallbackDispatcher(OMX *owner)
+    : mOwner(owner),
+      mDone(false) {
     pthread_attr_t attr;
     pthread_attr_init(&attr);
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
@@ -131,12 +96,12 @@
 }
 
 void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
-    NodeMeta *meta = static_cast<NodeMeta *>(msg.node);
-
-    sp<IOMXObserver> observer = meta->observer();
-    if (observer.get() != NULL) {
-        observer->on_message(msg);
+    OMXNodeInstance *instance = mOwner->findInstance(msg.node);
+    if (instance == NULL) {
+        LOGW("Would have dispatched a message to a node that's already gone.");
+        return;
     }
+    instance->onMessage(msg);
 }
 
 // static
@@ -214,46 +179,30 @@
     BufferMeta &operator=(const BufferMeta &);
 };
 
-// static
-OMX_CALLBACKTYPE OMX::kCallbacks = {
-    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
-};
-
-// static
-OMX_ERRORTYPE OMX::OnEvent(
-        OMX_IN OMX_HANDLETYPE hComponent,
-        OMX_IN OMX_PTR pAppData,
-        OMX_IN OMX_EVENTTYPE eEvent,
-        OMX_IN OMX_U32 nData1,
-        OMX_IN OMX_U32 nData2,
-        OMX_IN OMX_PTR pEventData) {
-    NodeMeta *meta = static_cast<NodeMeta *>(pAppData);
-    return meta->owner()->OnEvent(meta, eEvent, nData1, nData2, pEventData);
-}
-
-// static
-OMX_ERRORTYPE OMX::OnEmptyBufferDone(
-        OMX_IN OMX_HANDLETYPE hComponent,
-        OMX_IN OMX_PTR pAppData,
-        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
-    NodeMeta *meta = static_cast<NodeMeta *>(pAppData);
-    return meta->owner()->OnEmptyBufferDone(meta, pBuffer);
-}
-
-// static
-OMX_ERRORTYPE OMX::OnFillBufferDone(
-        OMX_IN OMX_HANDLETYPE hComponent,
-        OMX_IN OMX_PTR pAppData,
-        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
-    NodeMeta *meta = static_cast<NodeMeta *>(pAppData);
-    return meta->owner()->OnFillBufferDone(meta, pBuffer);
-}
-
 OMX::OMX()
-    : mDispatcher(new CallbackDispatcher) {
+    : mDispatcher(new CallbackDispatcher(this)),
+      mNodeCounter(0) {
 }
 
-status_t OMX::list_nodes(List<String8> *list) {
+void OMX::binderDied(const wp<IBinder> &the_late_who) {
+    OMXNodeInstance *instance;
+
+    {
+        Mutex::Autolock autoLock(mLock);
+
+        ssize_t index = mLiveNodes.indexOfKey(the_late_who);
+        CHECK(index >= 0);
+
+        instance = mLiveNodes.editValueAt(index);
+        mLiveNodes.removeItemsAt(index);
+
+        invalidateNodeID_l(instance->nodeID());
+    }
+
+    instance->onObserverDied();
+}
+
+status_t OMX::listNodes(List<String8> *list) {
     OMX_MasterInit();  // XXX Put this somewhere else.
 
     list->clear();
@@ -270,204 +219,132 @@
     return OK;
 }
 
-status_t OMX::allocate_node(const char *name, node_id *node) {
+status_t OMX::allocateNode(
+        const char *name, const sp<IOMXObserver> &observer, node_id *node) {
     Mutex::Autolock autoLock(mLock);
 
     *node = 0;
 
     OMX_MasterInit();  // XXX Put this somewhere else.
 
-    NodeMeta *meta = new NodeMeta(this);
+    OMXNodeInstance *instance = new OMXNodeInstance(this, observer);
 
     OMX_HANDLETYPE handle;
     OMX_ERRORTYPE err = OMX_MasterGetHandle(
-            &handle, const_cast<char *>(name), meta, &kCallbacks);
+            &handle, const_cast<char *>(name), instance,
+            &OMXNodeInstance::kCallbacks);
 
     if (err != OMX_ErrorNone) {
         LOGV("FAILED to allocate omx component '%s'", name);
 
-        delete meta;
-        meta = NULL;
+        instance->onGetHandleFailed();
 
         return UNKNOWN_ERROR;
     }
 
-    meta->setHandle(handle);
+    *node = makeNodeID(instance);
 
-    *node = meta;
+    instance->setHandle(*node, handle);
+
+    mLiveNodes.add(observer->asBinder(), instance);
+    observer->asBinder()->linkToDeath(this);
 
     return OK;
 }
 
-status_t OMX::free_node(node_id node) {
-    Mutex::Autolock autoLock(mLock);
+status_t OMX::freeNode(node_id node) {
+    OMXNodeInstance *instance = findInstance(node);
 
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
+    ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
+    CHECK(index >= 0);
+    mLiveNodes.removeItemsAt(index);
+    instance->observer()->asBinder()->unlinkToDeath(this);
 
-    OMX_ERRORTYPE err = OMX_MasterFreeHandle(meta->handle());
-
-    delete meta;
-    meta = NULL;
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return instance->freeNode();
 }
 
-status_t OMX::send_command(
+status_t OMX::sendCommand(
         node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
-    Mutex::Autolock autoLock(mLock);
-
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err = OMX_SendCommand(meta->handle(), cmd, param, NULL);
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return findInstance(node)->sendCommand(cmd, param);
 }
 
-status_t OMX::get_parameter(
+status_t OMX::getParameter(
         node_id node, OMX_INDEXTYPE index,
         void *params, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err = OMX_GetParameter(meta->handle(), index, params);
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return findInstance(node)->getParameter(
+            index, params, size);
 }
 
-status_t OMX::set_parameter(
+status_t OMX::setParameter(
         node_id node, OMX_INDEXTYPE index,
         const void *params, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_SetParameter(meta->handle(), index, const_cast<void *>(params));
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return findInstance(node)->setParameter(
+            index, params, size);
 }
 
-status_t OMX::get_config(
+status_t OMX::getConfig(
         node_id node, OMX_INDEXTYPE index,
         void *params, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err = OMX_GetConfig(meta->handle(), index, params);
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return findInstance(node)->getConfig(
+            index, params, size);
 }
 
-status_t OMX::set_config(
+status_t OMX::setConfig(
         node_id node, OMX_INDEXTYPE index,
         const void *params, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    NodeMeta *meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_SetConfig(meta->handle(), index, const_cast<void *>(params));
-
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+    return findInstance(node)->setConfig(
+            index, params, size);
 }
 
-status_t OMX::use_buffer(
+status_t OMX::useBuffer(
         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
         buffer_id *buffer) {
-    Mutex::Autolock autoLock(mLock);
-
-    BufferMeta *buffer_meta = new BufferMeta(this, params);
-
-    OMX_BUFFERHEADERTYPE *header;
-
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_UseBuffer(node_meta->handle(), &header, port_index, buffer_meta,
-                      params->size(), static_cast<OMX_U8 *>(params->pointer()));
-
-    if (err != OMX_ErrorNone) {
-        LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
-
-        delete buffer_meta;
-        buffer_meta = NULL;
-
-        *buffer = 0;
-        return UNKNOWN_ERROR;
-    }
-
-    *buffer = header;
-
-    return OK;
+    return findInstance(node)->useBuffer(
+            port_index, params, buffer);
 }
 
-status_t OMX::allocate_buffer(
+status_t OMX::allocateBuffer(
         node_id node, OMX_U32 port_index, size_t size,
         buffer_id *buffer) {
-    Mutex::Autolock autoLock(mLock);
-
-    BufferMeta *buffer_meta = new BufferMeta(this, size);
-
-    OMX_BUFFERHEADERTYPE *header;
-
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_AllocateBuffer(node_meta->handle(), &header, port_index,
-                           buffer_meta, size);
-
-    if (err != OMX_ErrorNone) {
-        delete buffer_meta;
-        buffer_meta = NULL;
-
-        *buffer = 0;
-        return UNKNOWN_ERROR;
-    }
-
-    *buffer = header;
-
-    return OK;
+    return findInstance(node)->allocateBuffer(
+            port_index, size, buffer);
 }
 
-status_t OMX::allocate_buffer_with_backup(
+status_t OMX::allocateBufferWithBackup(
         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
         buffer_id *buffer) {
-    Mutex::Autolock autoLock(mLock);
-
-    BufferMeta *buffer_meta = new BufferMeta(this, params, true);
-
-    OMX_BUFFERHEADERTYPE *header;
-
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_AllocateBuffer(
-                node_meta->handle(), &header, port_index, buffer_meta,
-                params->size());
-
-    if (err != OMX_ErrorNone) {
-        delete buffer_meta;
-        buffer_meta = NULL;
-
-        *buffer = 0;
-        return UNKNOWN_ERROR;
-    }
-
-    *buffer = header;
-
-    return OK;
+    return findInstance(node)->allocateBufferWithBackup(
+            port_index, params, buffer);
 }
 
-status_t OMX::free_buffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
-    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
-    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
+status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
+    return findInstance(node)->freeBuffer(
+            port_index, buffer);
+}
 
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-    OMX_ERRORTYPE err =
-        OMX_FreeBuffer(node_meta->handle(), port_index, header);
+status_t OMX::fillBuffer(node_id node, buffer_id buffer) {
+    return findInstance(node)->fillBuffer(buffer);
+}
 
-    delete buffer_meta;
-    buffer_meta = NULL;
+status_t OMX::emptyBuffer(
+        node_id node,
+        buffer_id buffer,
+        OMX_U32 range_offset, OMX_U32 range_length,
+        OMX_U32 flags, OMX_TICKS timestamp) {
+    return findInstance(node)->emptyBuffer(
+            buffer, range_offset, range_length, flags, timestamp);
+}
 
-    return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+status_t OMX::getExtensionIndex(
+        node_id node,
+        const char *parameter_name,
+        OMX_INDEXTYPE *index) {
+    return findInstance(node)->getExtensionIndex(
+            parameter_name, index);
 }
 
 OMX_ERRORTYPE OMX::OnEvent(
-        NodeMeta *meta,
+        node_id node,
         OMX_IN OMX_EVENTTYPE eEvent,
         OMX_IN OMX_U32 nData1,
         OMX_IN OMX_U32 nData2,
@@ -476,7 +353,7 @@
 
     omx_message msg;
     msg.type = omx_message::EVENT;
-    msg.node = meta;
+    msg.node = node;
     msg.u.event_data.event = eEvent;
     msg.u.event_data.data1 = nData1;
     msg.u.event_data.data2 = nData2;
@@ -485,14 +362,14 @@
 
     return OMX_ErrorNone;
 }
-    
+
 OMX_ERRORTYPE OMX::OnEmptyBufferDone(
-        NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
+        node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
     LOGV("OnEmptyBufferDone buffer=%p", pBuffer);
 
     omx_message msg;
     msg.type = omx_message::EMPTY_BUFFER_DONE;
-    msg.node = meta;
+    msg.node = node;
     msg.u.buffer_data.buffer = pBuffer;
 
     mDispatcher->post(msg);
@@ -501,14 +378,12 @@
 }
 
 OMX_ERRORTYPE OMX::OnFillBufferDone(
-        NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
+        node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
     LOGV("OnFillBufferDone buffer=%p", pBuffer);
-    BufferMeta *buffer_meta = static_cast<BufferMeta *>(pBuffer->pAppPrivate);
-    buffer_meta->CopyFromOMX(pBuffer);
 
     omx_message msg;
     msg.type = omx_message::FILL_BUFFER_DONE;
-    msg.node = meta;
+    msg.node = node;
     msg.u.extended_buffer_data.buffer = pBuffer;
     msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
     msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
@@ -521,64 +396,31 @@
     return OMX_ErrorNone;
 }
 
-status_t OMX::observe_node(
-        node_id node, const sp<IOMXObserver> &observer) {
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
+OMX::node_id OMX::makeNodeID(OMXNodeInstance *instance) {
+    // mLock is already held.
 
-    node_meta->setObserver(observer);
+    node_id node = (node_id)++mNodeCounter;
+    mNodeIDToInstance.add(node, instance);
 
-    return OK;
+    return node;
 }
 
-status_t OMX::fill_buffer(node_id node, buffer_id buffer) {
-    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
-    header->nFilledLen = 0;
-    header->nOffset = 0;
-    header->nFlags = 0;
+OMXNodeInstance *OMX::findInstance(node_id node) {
+    Mutex::Autolock autoLock(mLock);
 
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
+    ssize_t index = mNodeIDToInstance.indexOfKey(node);
 
-    OMX_ERRORTYPE err =
-        OMX_FillThisBuffer(node_meta->handle(), header);
-
-    return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR;
+    return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
 }
 
-status_t OMX::empty_buffer(
-        node_id node,
-        buffer_id buffer,
-        OMX_U32 range_offset, OMX_U32 range_length,
-        OMX_U32 flags, OMX_TICKS timestamp) {
-    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
-    header->nFilledLen = range_length;
-    header->nOffset = range_offset;
-    header->nFlags = flags;
-    header->nTimeStamp = timestamp;
-
-    BufferMeta *buffer_meta =
-        static_cast<BufferMeta *>(header->pAppPrivate);
-    buffer_meta->CopyToOMX(header);
-
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-
-    OMX_ERRORTYPE err =
-        OMX_EmptyThisBuffer(node_meta->handle(), header);
-
-    return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR;
+void OMX::invalidateNodeID(node_id node) {
+    Mutex::Autolock autoLock(mLock);
+    invalidateNodeID_l(node);
 }
 
-status_t OMX::get_extension_index(
-        node_id node,
-        const char *parameter_name,
-        OMX_INDEXTYPE *index) {
-    NodeMeta *node_meta = static_cast<NodeMeta *>(node);
-
-    OMX_ERRORTYPE err =
-        OMX_GetExtensionIndex(
-                node_meta->handle(),
-                const_cast<char *>(parameter_name), index);
-
-    return err == OMX_ErrorNone ? OK : UNKNOWN_ERROR;
+void OMX::invalidateNodeID_l(node_id node) {
+    // mLock is held.
+    mNodeIDToInstance.removeItem(node);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
new file mode 100644
index 0000000..d277587
--- /dev/null
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -0,0 +1,373 @@
+/*
+ * 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 "OMXNodeInstance"
+#include <utils/Log.h>
+
+#include "../include/OMXNodeInstance.h"
+
+#include "pv_omxcore.h"
+
+#include <binder/IMemory.h>
+#include <media/stagefright/MediaDebug.h>
+
+namespace android {
+
+struct BufferMeta {
+    BufferMeta(const sp<IMemory> &mem, bool is_backup = false)
+        : mMem(mem),
+          mIsBackup(is_backup) {
+    }
+
+    BufferMeta(size_t size)
+        : mSize(size),
+          mIsBackup(false) {
+    }
+
+    void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
+        if (!mIsBackup) {
+            return;
+        }
+
+        memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
+               header->pBuffer + header->nOffset,
+               header->nFilledLen);
+    }
+
+    void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
+        if (!mIsBackup) {
+            return;
+        }
+
+        memcpy(header->pBuffer + header->nOffset,
+               (const OMX_U8 *)mMem->pointer() + header->nOffset,
+               header->nFilledLen);
+    }
+
+private:
+    sp<IMemory> mMem;
+    size_t mSize;
+    bool mIsBackup;
+
+    BufferMeta(const BufferMeta &);
+    BufferMeta &operator=(const BufferMeta &);
+};
+
+// static
+OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
+    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
+};
+
+OMXNodeInstance::OMXNodeInstance(
+        OMX *owner, const sp<IOMXObserver> &observer)
+    : mOwner(owner),
+      mNodeID(NULL),
+      mHandle(NULL),
+      mObserver(observer) {
+}
+
+OMXNodeInstance::~OMXNodeInstance() {
+    CHECK_EQ(mHandle, NULL);
+}
+
+void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
+    CHECK_EQ(mHandle, NULL);
+    mNodeID = node_id;
+    mHandle = handle;
+}
+
+OMX *OMXNodeInstance::owner() {
+    return mOwner;
+}
+
+sp<IOMXObserver> OMXNodeInstance::observer() {
+    return mObserver;
+}
+
+OMX::node_id OMXNodeInstance::nodeID() {
+    return mNodeID;
+}
+
+static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
+    return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR;
+}
+
+status_t OMXNodeInstance::freeNode() {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_MasterFreeHandle(mHandle);
+    mHandle = NULL;
+
+    if (err != OMX_ErrorNone) {
+        LOGE("FreeHandle FAILED with error 0x%08x.", err);
+    }
+
+    mOwner->invalidateNodeID(mNodeID);
+    mNodeID = NULL;
+
+    LOGI("OMXNodeInstance going away.");
+    delete this;
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::sendCommand(
+        OMX_COMMANDTYPE cmd, OMX_S32 param) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::getParameter(
+        OMX_INDEXTYPE index, void *params, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::setParameter(
+        OMX_INDEXTYPE index, const void *params, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_SetParameter(
+            mHandle, index, const_cast<void *>(params));
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::getConfig(
+        OMX_INDEXTYPE index, void *params, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::setConfig(
+        OMX_INDEXTYPE index, const void *params, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_SetConfig(
+            mHandle, index, const_cast<void *>(params));
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::useBuffer(
+        OMX_U32 portIndex, const sp<IMemory> &params,
+        OMX::buffer_id *buffer) {
+    Mutex::Autolock autoLock(mLock);
+
+    BufferMeta *buffer_meta = new BufferMeta(params);
+
+    OMX_BUFFERHEADERTYPE *header;
+
+    OMX_ERRORTYPE err = OMX_UseBuffer(
+            mHandle, &header, portIndex, buffer_meta,
+            params->size(), static_cast<OMX_U8 *>(params->pointer()));
+
+    if (err != OMX_ErrorNone) {
+        LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
+
+        delete buffer_meta;
+        buffer_meta = NULL;
+
+        *buffer = 0;
+
+        return UNKNOWN_ERROR;
+    }
+
+    *buffer = header;
+
+    return OK;
+}
+
+status_t OMXNodeInstance::allocateBuffer(
+        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer) {
+    Mutex::Autolock autoLock(mLock);
+
+    BufferMeta *buffer_meta = new BufferMeta(size);
+
+    OMX_BUFFERHEADERTYPE *header;
+
+    OMX_ERRORTYPE err = OMX_AllocateBuffer(
+            mHandle, &header, portIndex, buffer_meta, size);
+
+    if (err != OMX_ErrorNone) {
+        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
+
+        delete buffer_meta;
+        buffer_meta = NULL;
+
+        *buffer = 0;
+
+        return UNKNOWN_ERROR;
+    }
+
+    *buffer = header;
+
+    return OK;
+}
+
+status_t OMXNodeInstance::allocateBufferWithBackup(
+        OMX_U32 portIndex, const sp<IMemory> &params,
+        OMX::buffer_id *buffer) {
+    Mutex::Autolock autoLock(mLock);
+
+    BufferMeta *buffer_meta = new BufferMeta(params, true);
+
+    OMX_BUFFERHEADERTYPE *header;
+
+    OMX_ERRORTYPE err = OMX_AllocateBuffer(
+            mHandle, &header, portIndex, buffer_meta, params->size());
+
+    if (err != OMX_ErrorNone) {
+        LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
+
+        delete buffer_meta;
+        buffer_meta = NULL;
+
+        *buffer = 0;
+
+        return UNKNOWN_ERROR;
+    }
+
+    *buffer = header;
+
+    return OK;
+}
+
+status_t OMXNodeInstance::freeBuffer(
+        OMX_U32 portIndex, OMX::buffer_id buffer) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+    BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
+
+    OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
+
+    delete buffer_meta;
+    buffer_meta = NULL;
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+    header->nFilledLen = 0;
+    header->nOffset = 0;
+    header->nFlags = 0;
+
+    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::emptyBuffer(
+        OMX::buffer_id buffer,
+        OMX_U32 rangeOffset, OMX_U32 rangeLength,
+        OMX_U32 flags, OMX_TICKS timestamp) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+    header->nFilledLen = rangeLength;
+    header->nOffset = rangeOffset;
+    header->nFlags = flags;
+    header->nTimeStamp = timestamp;
+
+    BufferMeta *buffer_meta =
+        static_cast<BufferMeta *>(header->pAppPrivate);
+    buffer_meta->CopyToOMX(header);
+
+    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
+
+    return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::getExtensionIndex(
+        const char *parameterName, OMX_INDEXTYPE *index) {
+    Mutex::Autolock autoLock(mLock);
+
+    OMX_ERRORTYPE err = OMX_GetExtensionIndex(
+            mHandle, const_cast<char *>(parameterName), index);
+
+    return StatusFromOMXError(err);
+}
+
+void OMXNodeInstance::onMessage(const omx_message &msg) {
+    if (msg.type == omx_message::FILL_BUFFER_DONE) {
+        OMX_BUFFERHEADERTYPE *buffer =
+            static_cast<OMX_BUFFERHEADERTYPE *>(
+                    msg.u.extended_buffer_data.buffer);
+
+        BufferMeta *buffer_meta =
+            static_cast<BufferMeta *>(buffer->pAppPrivate);
+
+        buffer_meta->CopyFromOMX(buffer);
+    }
+
+    mObserver->onMessage(msg);
+}
+
+void OMXNodeInstance::onObserverDied() {
+    LOGE("!!! Observer died. Quickly, do something, ... anything...");
+
+    // Try to force shutdown of the node and hope for the best.
+    freeNode();
+}
+
+void OMXNodeInstance::onGetHandleFailed() {
+    delete this;
+}
+
+// static
+OMX_ERRORTYPE OMXNodeInstance::OnEvent(
+        OMX_IN OMX_HANDLETYPE hComponent,
+        OMX_IN OMX_PTR pAppData,
+        OMX_IN OMX_EVENTTYPE eEvent,
+        OMX_IN OMX_U32 nData1,
+        OMX_IN OMX_U32 nData2,
+        OMX_IN OMX_PTR pEventData) {
+    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
+    return instance->owner()->OnEvent(
+            instance->nodeID(), eEvent, nData1, nData2, pEventData);
+}
+
+// static
+OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
+        OMX_IN OMX_HANDLETYPE hComponent,
+        OMX_IN OMX_PTR pAppData,
+        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
+    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
+    return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
+}
+
+// static
+OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
+        OMX_IN OMX_HANDLETYPE hComponent,
+        OMX_IN OMX_PTR pAppData,
+        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
+    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
+    return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/string.cpp b/media/libstagefright/string.cpp
index a4a1937..bd6204b 100644
--- a/media/libstagefright/string.cpp
+++ b/media/libstagefright/string.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "include/string.h"
+#include "include/stagefright_string.h"
 
 namespace android {
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index 0ae354a..6e3f5e3 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -309,6 +309,8 @@
     }
 
     public boolean validateMemoryResult (int startPid, int startMemory, Writer output) throws Exception {
+        //Wait for 10 seconds to make sure the memory settle.
+        Thread.sleep(10000);
         mEndPid = getMediaserverPid();
         mEndMemory = getMediaserverVsize();
         Log.v(TAG, "End Memory " + mEndMemory);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
index 90d6ffa..daa0ca7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
@@ -41,7 +41,7 @@
     private static final int NUMBER_OF_RANDOM_REPOSITION_AND_PLAY = 10;
     private static final int NUMBER_OF_RANDOM_REPOSITION_AND_PLAY_SHORT = 5;
     private static final int NUMBER_OF_STRESS_LOOPS = 500;
-    private static final int PLAYBACK_END_TOLERANCE = 5000;
+    private static final int PLAYBACK_END_TOLERANCE = 30000;
     private static final int WAIT_UNTIL_PLAYBACK_FINISH = 515000 ;
 
     public MediaPlayerStressTest() {
@@ -112,10 +112,11 @@
                 if (random_no_of_seek == 0) {
                     random_no_of_seek = 1;
                 }
-                // Random seek and play
+                Log.v(TAG, "random_seek = " + random_no_of_seek);
+                // Play for 10 seconds then random seekTo
                 for (int j = 0; j < random_no_of_seek; j++) {
                     random_play_time =
-                        generator.nextInt(video_duration / 2);
+                        generator.nextInt(video_duration / 100);
                     Log.v(TAG, "Play time = " + random_play_time);
                     Thread.sleep(random_play_time);
                     random_seek_time =
@@ -123,12 +124,13 @@
                     Log.v(TAG, "Seek time = " + random_seek_time);
                     mp.seekTo(random_seek_time);
                 }
-                //wait until the movie finish and check the current position
-                //Make sure the wait time is long enough
-                long wait_until_playback_finish = video_duration - random_seek_time + PLAYBACK_END_TOLERANCE * 2;
-                Thread.sleep(wait_until_playback_finish);
+                //Seek to 10s from the end of the video
+                mp.seekTo(video_duration - 10000);
+                //After reposition, play 30 seconds the video should be finished.
+                Thread.sleep(PLAYBACK_END_TOLERANCE);
                 Log.v(TAG, "CurrentPosition = " + mp.getCurrentPosition());
-                if ( mp.isPlaying() || mp.getCurrentPosition() > (video_duration + PLAYBACK_END_TOLERANCE)){
+                if ( mp.isPlaying() || mp.getCurrentPosition()
+                        > (video_duration)){
                     assertTrue("Current PlayTime greater than duration", false);
                 }
                 mp.release();
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 695d0616..f485d26 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -18,7 +18,6 @@
 
 import java.io.Writer;
 import java.util.ArrayList;
-import java.util.concurrent.Semaphore;
 
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGL11;
@@ -30,6 +29,8 @@
 import javax.microedition.khronos.opengles.GL10;
 
 import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.os.SystemProperties;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.SurfaceHolder;
@@ -681,7 +682,10 @@
         }
         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
             int[] num_config = new int[1];
-            egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config);
+            if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
+                    num_config)) {
+                throw new IllegalArgumentException("eglChooseConfig failed");
+            }
 
             int numConfigs = num_config[0];
 
@@ -691,8 +695,10 @@
             }
 
             EGLConfig[] configs = new EGLConfig[numConfigs];
-            egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
-                    num_config);
+            if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
+                    num_config)) {
+                throw new IllegalArgumentException("eglChooseConfig#2 failed");
+            }
             EGLConfig config = chooseConfig(egl, display, configs);
             if (config == null) {
                 throw new IllegalArgumentException("No config chosen");
@@ -817,11 +823,17 @@
              */
             mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
 
+            if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
+                throw new RuntimeException("eglGetDisplay failed");
+            }
+
             /*
              * We can now initialize EGL for that display
              */
             int[] version = new int[2];
-            mEgl.eglInitialize(mEglDisplay, version);
+            if(!mEgl.eglInitialize(mEglDisplay, version)) {
+                throw new RuntimeException("eglInitialize failed");
+            }
             mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
 
             /*
@@ -966,16 +978,12 @@
              * accesses EGL.
              */
             try {
-                try {
-                sEglSemaphore.acquire();
-                } catch (InterruptedException e) {
-                    return;
-                }
+                sGLAccessLock.acquire();
                 guardedRun();
             } catch (InterruptedException e) {
                 // fall thru and exit normally
             } finally {
-                sEglSemaphore.release();
+                sGLAccessLock.release();
             }
         }
 
@@ -1040,6 +1048,7 @@
                     }
                     if (changed) {
                         gl = (GL10) mEglHelper.createSurface(getHolder());
+                        sGLAccessLock.checkGLDriver(gl);
                         tellRendererSurfaceChanged = true;
                     }
                     if (tellRendererSurfaceCreated) {
@@ -1241,7 +1250,56 @@
         }
     }
 
-    private static final Semaphore sEglSemaphore = new Semaphore(1);
+    private static class GLAccessLock {
+        public synchronized void acquire() throws InterruptedException {
+            if (! mGLESVersionCheckComplete) {
+                mGLESVersion = SystemProperties.getInt(
+                        "ro.opengles.version",
+                        ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
+                if (mGLESVersion >= kGLES_20) {
+                    mMultipleGLESContextsAllowed = true;
+                }
+                mGLESVersionCheckComplete = true;
+            }
+
+            while ((! mMultipleGLESContextsAllowed)
+                    && mGLContextCount > 0) {
+                wait();
+            }
+
+            mGLContextCount++;
+
+        }
+
+        public synchronized void release() {
+            mGLContextCount--;
+            notifyAll();
+        }
+
+        public synchronized void checkGLDriver(GL10 gl) {
+            if (! mGLESDriverCheckComplete) {
+                if (mGLESVersion < kGLES_20) {
+                    String renderer = gl.glGetString(GL10.GL_RENDERER);
+                    mMultipleGLESContextsAllowed =
+                        ! renderer.startsWith(kMSM7K_RENDERER_PREFIX);
+                    notifyAll();
+                }
+                mGLESDriverCheckComplete = true;
+            }
+        }
+
+        private boolean mGLESVersionCheckComplete;
+        private int mGLESVersion;
+        private boolean mGLESDriverCheckComplete;
+        private boolean mMultipleGLESContextsAllowed;
+        private int mGLContextCount;
+        private static final int kGLES_20 = 0x20000;
+        private static final String kMSM7K_RENDERER_PREFIX =
+            "Q3Dimension MSM7500 ";
+    };
+
+    private static GLAccessLock sGLAccessLock = new GLAccessLock();
+
     private boolean mSizeChanged = true;
 
     private GLThread mGLThread;
diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp
index 867459d..73b2355 100644
--- a/opengl/libagl/copybit.cpp
+++ b/opengl/libagl/copybit.cpp
@@ -41,11 +41,12 @@
 namespace android {
 
 static void textureToCopyBitImage(
-        const GGLSurface* surface, buffer_handle_t buffer, copybit_image_t* img) 
+        const GGLSurface* surface, int32_t opFormat, 
+        buffer_handle_t buffer, copybit_image_t* img) 
 {
     img->w      = surface->stride;
     img->h      = surface->height;
-    img->format = surface->format;
+    img->format = opFormat;
     img->base   = surface->data;
     img->handle = (native_handle_t *)buffer;
 }
@@ -207,39 +208,13 @@
     int planeAlpha = 255;
     static const int tmu = 0;
     texture_t& tev(c->rasterizer.state.texture[tmu]);
-    bool srcTextureHasAlpha = hasAlpha(textureObject->surface.format);
+    int32_t opFormat = textureObject->surface.format;
+    const bool srcTextureHasAlpha = hasAlpha(opFormat);
     if (!srcTextureHasAlpha) {
         planeAlpha = fixedToByte(c->currentColorClamped.a);
     }
 
-    switch (tev.env) {
-    case GGL_REPLACE:
-        break;
-    case GGL_MODULATE:
-        if (! (c->currentColorClamped.r == FIXED_ONE &&
-               c->currentColorClamped.g == FIXED_ONE &&
-               c->currentColorClamped.b == FIXED_ONE)) {
-            LOGD_IF(DEBUG_COPYBIT, 
-                    "MODULATE and non white color (%08x, %08x, %08x)",
-                    c->currentColorClamped.r,
-                    c->currentColorClamped.g,
-                    c->currentColorClamped.b);
-            return false;
-        }
-        if (srcTextureHasAlpha && c->currentColorClamped.a < FIXED_ONE) {
-            LOGD_IF(DEBUG_COPYBIT, 
-                    "MODULATE and texture w/alpha and alpha=%08x)",
-                    c->currentColorClamped.a);
-            return false;
-        }
-        break;
-
-    default:
-        // Incompatible texture environment.
-        LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment");
-        return false;
-    }
-
+    const bool cbHasAlpha = hasAlpha(cbSurface.format);
     bool blending = false;
     if ((enables & GGL_ENABLE_BLENDING)
             && !(c->rasterizer.state.blend.src == GL_ONE
@@ -262,32 +237,60 @@
         }
         blending = true;
     } else {
-        // No blending is OK if we are not using alpha.
-        if (srcTextureHasAlpha || planeAlpha != 255) {
-            // Incompatible alpha
-            LOGD_IF(DEBUG_COPYBIT, "incompatible alpha");
-            return false;
+        if (cbHasAlpha) {
+            // NOTE: the result will be slightly wrong in this case because
+            // the destination alpha channel will be set to 1.0 instead of
+            // the iterated alpha value. *shrug*.
+        }
+        // disable plane blending and src blending for supported formats
+        planeAlpha = 255;
+        if (opFormat == COPYBIT_FORMAT_RGBA_8888) {
+            opFormat = COPYBIT_FORMAT_RGBX_8888;
+        } else {
+            if (srcTextureHasAlpha) {
+                LOGD_IF(DEBUG_COPYBIT, "texture format requires blending");
+                return false;
+            }
         }
     }
 
-    if (srcTextureHasAlpha && planeAlpha != 255) {
-        // Can't do two types of alpha at once.
-        LOGD_IF(DEBUG_COPYBIT, "src alpha and plane alpha");
+    switch (tev.env) {
+    case GGL_REPLACE:
+        break;
+    case GGL_MODULATE:
+        // only cases allowed is:
+        // RGB  source, color={1,1,1,a} -> can be done with GL_REPLACE
+        // RGBA source, color={1,1,1,1} -> can be done with GL_REPLACE
+        if (blending) {
+            if (c->currentColorClamped.r == c->currentColorClamped.a &&
+                c->currentColorClamped.g == c->currentColorClamped.a &&
+                c->currentColorClamped.b == c->currentColorClamped.a) {
+                // TODO: Need to emulate: RGBA source, color={a,a,a,a} / premult
+                // and RGBA source, color={1,1,1,a} / regular-blending
+                // (both are equivalent)
+            }
+        }
+        LOGD_IF(DEBUG_COPYBIT, "GGL_MODULATE");
+        return false;
+    default:
+        // Incompatible texture environment.
+        LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment");
         return false;
     }
 
+
     // LOGW("calling copybits");
 
     copybit_device_t* copybit = c->copybits.blitEngine;
 
     copybit_image_t dst;
     buffer_handle_t target_hnd = c->copybits.drawSurfaceBuffer;
-    textureToCopyBitImage(&cbSurface, target_hnd, &dst);
+    textureToCopyBitImage(&cbSurface, cbSurface.format, target_hnd, &dst);
     copybit_rect_t drect = {x, y, x+w, y+h};
 
     copybit_image_t src;
     buffer_handle_t source_hnd = textureObject->buffer->handle;
-    textureToCopyBitImage(&textureObject->surface, source_hnd, &src);
+    textureToCopyBitImage(&textureObject->surface, opFormat, source_hnd, &src);
     copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
 
     copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 37628b7..d04900e 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -953,12 +953,17 @@
         { EGL_BIND_TO_TEXTURE_RGB,        EGL_FALSE                         },
         { EGL_MIN_SWAP_INTERVAL,          1                                 },
         { EGL_MAX_SWAP_INTERVAL,          1                                 },
+        { EGL_LUMINANCE_SIZE,             0                                 },
+        { EGL_ALPHA_MASK_SIZE,            0                                 },
+        { EGL_COLOR_BUFFER_TYPE,          EGL_RGB_BUFFER                    },
         { EGL_RENDERABLE_TYPE,            EGL_OPENGL_ES_BIT                 },
+        { EGL_CONFORMANT,                 0                                 }
 };
 
 // These configs can override the base attribute list
 // NOTE: when adding a config here, don't forget to update eglCreate*Surface()
 
+
 static config_pair_t const config_0_attribute_list[] = {
         { EGL_BUFFER_SIZE,     16 },
         { EGL_ALPHA_SIZE,       0 },
@@ -1062,10 +1067,18 @@
         { EGL_BIND_TO_TEXTURE_RGB,        config_management_t::exact   },
         { EGL_MIN_SWAP_INTERVAL,          config_management_t::exact   },
         { EGL_MAX_SWAP_INTERVAL,          config_management_t::exact   },
+        { EGL_LUMINANCE_SIZE,             config_management_t::atLeast },
+        { EGL_ALPHA_MASK_SIZE,            config_management_t::atLeast },
+        { EGL_COLOR_BUFFER_TYPE,          config_management_t::exact   },
+        { EGL_RENDERABLE_TYPE,            config_management_t::mask    },
+        { EGL_CONFORMANT,                 config_management_t::mask    }
 };
 
+
 static config_pair_t const config_defaults[] = {
-        { EGL_SURFACE_TYPE,        EGL_WINDOW_BIT },
+    // attributes that are not specified are simply ignored, if a particular
+    // one needs not be ignored, it must be specified here, eg:
+    // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
 };
 
 // ----------------------------------------------------------------------------
@@ -1513,7 +1526,7 @@
         numAttributes++;
         EGLint attr = *attrib_list++;
         EGLint val  = *attrib_list++;
-        for (int i=0 ; i<numConfigs ; i++) {
+        for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
             if (!(possibleMatch & (1<<i)))
                 continue;
             if (isAttributeMatching(i, attr, val) == 0) {
@@ -1523,15 +1536,15 @@
     }
 
     // now, handle the attributes which have a useful default value
-    for (size_t j=0 ; j<NELEM(config_defaults) ; j++) {
-        // see if this attribute was specified, if not apply its
+    for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
+        // see if this attribute was specified, if not, apply its
         // default value
         if (binarySearch<config_pair_t>(
                 (config_pair_t const*)attrib_list,
                 0, numAttributes-1,
                 config_defaults[j].key) < 0)
         {
-            for (int i=0 ; i<numConfigs ; i++) {
+            for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
                 if (!(possibleMatch & (1<<i)))
                     continue;
                 if (isAttributeMatching(i,
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index 90e6d29..13d078e 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -1252,6 +1252,11 @@
         ogles_error(c, GL_INVALID_OPERATION);
         return;
     }
+
+    if (format != tex->internalformat) {
+        ogles_error(c, GL_INVALID_OPERATION);
+        return;
+    }
     if ((xoffset + width  > GLsizei(surface.width)) ||
         (yoffset + height > GLsizei(surface.height))) {
         ogles_error(c, GL_INVALID_VALUE);
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 9578452..6d20e80 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -32,6 +32,10 @@
 LOCAL_CFLAGS += -DADRENO130=1
 endif
 
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+  LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 installed_libEGL := $(LOCAL_INSTALLED_MODULE)
 
@@ -78,6 +82,10 @@
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+  LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 
 
@@ -107,4 +115,8 @@
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+  LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 7e7da1b..5d6ac26 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -128,7 +128,7 @@
     return 0;
 }
 
-void* Loader::open(EGLNativeDisplayType display, int impl, gl_hooks_t* hooks)
+void* Loader::open(EGLNativeDisplayType display, int impl, egl_connection_t* cnx)
 {
     /*
      * TODO: if we don't find display/0, then use 0/0
@@ -144,22 +144,22 @@
     char const* tag = getTag(index, impl);
     if (tag) {
         snprintf(path, PATH_MAX, format, "GLES", tag);
-        dso = load_driver(path, hooks, EGL | GLESv1_CM | GLESv2);
+        dso = load_driver(path, cnx, EGL | GLESv1_CM | GLESv2);
         if (dso) {
             hnd = new driver_t(dso);
         } else {
             // Always load EGL first
             snprintf(path, PATH_MAX, format, "EGL", tag);
-            dso = load_driver(path, hooks, EGL);
+            dso = load_driver(path, cnx, EGL);
             if (dso) {
                 hnd = new driver_t(dso);
 
                 // TODO: make this more automated
                 snprintf(path, PATH_MAX, format, "GLESv1_CM", tag);
-                hnd->set( load_driver(path, hooks, GLESv1_CM), GLESv1_CM );
+                hnd->set( load_driver(path, cnx, GLESv1_CM), GLESv1_CM );
 
                 snprintf(path, PATH_MAX, format, "GLESv2", tag);
-                hnd->set( load_driver(path, hooks, GLESv2), GLESv2 );
+                hnd->set( load_driver(path, cnx, GLESv2), GLESv2 );
             }
         }
     }
@@ -223,7 +223,7 @@
 }
 
 void *Loader::load_driver(const char* driver_absolute_path,
-        gl_hooks_t* hooks, uint32_t mask)
+        egl_connection_t* cnx, uint32_t mask)
 {
     if (access(driver_absolute_path, R_OK)) {
         // this happens often, we don't want to log an error
@@ -245,7 +245,7 @@
         LOGE_IF(!getProcAddress, 
                 "can't find eglGetProcAddress() in %s", driver_absolute_path);
 
-        gl_hooks_t::egl_t* egl = &hooks->egl;
+        egl_t* egl = &cnx->egl;
         __eglMustCastToProperFunctionPointerType* curr =
             (__eglMustCastToProperFunctionPointerType*)egl;
         char const * const * api = egl_names;
@@ -266,14 +266,16 @@
     }
     
     if (mask & GLESv1_CM) {
-        init_api(dso, gl_names,  
-                (__eglMustCastToProperFunctionPointerType*)&hooks->gl, 
-                getProcAddress);
+        init_api(dso, gl_names,
+            (__eglMustCastToProperFunctionPointerType*)
+                &cnx->hooks[GLESv1_INDEX]->gl,
+            getProcAddress);
     }
 
     if (mask & GLESv2) {
-      init_api(dso, gl2_names, 
-            (__eglMustCastToProperFunctionPointerType*)&hooks->gl2, 
+      init_api(dso, gl_names,
+            (__eglMustCastToProperFunctionPointerType*)
+                &cnx->hooks[GLESv2_INDEX]->gl,
             getProcAddress);
     }
     
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 69f6dd5..8659b0b 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -32,7 +32,7 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
-struct gl_hooks_t;
+struct egl_connection_t;
 
 class Loader : public Singleton<Loader>
 {
@@ -69,12 +69,12 @@
 public:
     ~Loader();
     
-    void* open(EGLNativeDisplayType display, int impl, gl_hooks_t* hooks);
+    void* open(EGLNativeDisplayType display, int impl, egl_connection_t* cnx);
     status_t close(void* driver);
     
 private:
     Loader();
-    void *load_driver(const char* driver, gl_hooks_t* hooks, uint32_t mask);
+    void *load_driver(const char* driver, egl_connection_t* cnx, uint32_t mask);
 
     static __attribute__((noinline))
     void init_api(void* dso, 
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index d1ddcd3..3efb678 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -164,7 +164,7 @@
     };
 
     uint32_t    magic;
-    DisplayImpl disp[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+    DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS];
     EGLint      numTotalConfigs;
     volatile int32_t refs;
     
@@ -195,8 +195,9 @@
     typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
     
     egl_context_t(EGLDisplay dpy, EGLContext context,
-            int impl, egl_connection_t const* cnx) 
-    : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx)
+            int impl, egl_connection_t const* cnx, int version) 
+    : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx),
+      version(version)
     {
     }
     EGLDisplay                  dpy;
@@ -205,6 +206,7 @@
     EGLSurface                  draw;
     int                         impl;
     egl_connection_t const*     cnx;
+    int                         version;
 };
 
 struct egl_image_t : public egl_object_t
@@ -218,7 +220,7 @@
     }
     EGLDisplay dpy;
     EGLConfig context;
-    EGLImageKHR images[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+    EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
 };
 
 typedef egl_surface_t::Ref  SurfaceRef;
@@ -236,14 +238,15 @@
 
 // ----------------------------------------------------------------------------
 
-egl_connection_t gEGLImpl[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
 static egl_display_t gDisplay[NUM_DISPLAYS];
 static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_key_t gEGLThreadLocalStorageKey = -1;
 
 // ----------------------------------------------------------------------------
 
-EGLAPI gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS];
+EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+EGLAPI gl_hooks_t gHooksNoContext;
 EGLAPI pthread_key_t gGLWrapperKey = -1;
 
 // ----------------------------------------------------------------------------
@@ -434,10 +437,10 @@
 #endif
     uint32_t addr = (uint32_t)((void*)gl_no_context);
     android_memset32(
-            (uint32_t*)(void*)&gHooks[IMPL_NO_CONTEXT], 
+            (uint32_t*)(void*)&gHooksNoContext, 
             addr, 
-            sizeof(gHooks[IMPL_NO_CONTEXT]));
-    setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
+            sizeof(gHooksNoContext));
+    setGlThreadSpecific(&gHooksNoContext);
 }
 
 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
@@ -479,7 +482,7 @@
     if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
 
     impl = uintptr_t(config)>>24;
-    if (uint32_t(impl) >= IMPL_NUM_DRIVERS_IMPLEMENTATIONS) {
+    if (uint32_t(impl) >= IMPL_NUM_IMPLEMENTATIONS) {
         return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
     } 
     index = uintptr_t(config) & 0xFFFFFF;
@@ -559,10 +562,11 @@
 
     cnx = &gEGLImpl[IMPL_SOFTWARE];
     if (cnx->dso == 0) {
-        cnx->hooks = &gHooks[IMPL_SOFTWARE];
-        cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx->hooks);
+        cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
+        cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
+        cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
         if (cnx->dso) {
-            EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+            EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
             LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
             d->disp[IMPL_SOFTWARE].dpy = dpy; 
             if (dpy == EGL_NO_DISPLAY) {
@@ -577,10 +581,11 @@
         char value[PROPERTY_VALUE_MAX];
         property_get("debug.egl.hw", value, "1");
         if (atoi(value) != 0) {
-            cnx->hooks = &gHooks[IMPL_HARDWARE];
-            cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx->hooks);
+            cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
+            cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
+            cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
             if (cnx->dso) {
-                EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+                EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
                 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
                 d->disp[IMPL_HARDWARE].dpy = dpy; 
                 if (dpy == EGL_NO_DISPLAY) {
@@ -645,12 +650,12 @@
         return EGL_TRUE;
     }
     
-    setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
+    setGlThreadSpecific(&gHooksNoContext);
     
     // initialize each EGL and
     // build our own extension string first, based on the extension we know
     // and the extension supported by our client implementation
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         cnx->major = -1;
         cnx->minor = -1;
@@ -668,13 +673,13 @@
          */
         if (i == IMPL_HARDWARE) {
             dp->disp[i].dpy =
-                cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+                cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
         }
 #endif
 
 
         EGLDisplay idpy = dp->disp[i].dpy;
-        if (cnx->hooks->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
+        if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
             //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
             //        i, idpy, cnx->major, cnx->minor, cnx);
 
@@ -683,29 +688,29 @@
 
             // get the query-strings for this display for each implementation
             dp->disp[i].queryString.vendor =
-                cnx->hooks->egl.eglQueryString(idpy, EGL_VENDOR);
+                cnx->egl.eglQueryString(idpy, EGL_VENDOR);
             dp->disp[i].queryString.version =
-                cnx->hooks->egl.eglQueryString(idpy, EGL_VERSION);
+                cnx->egl.eglQueryString(idpy, EGL_VERSION);
             dp->disp[i].queryString.extensions =
-                    cnx->hooks->egl.eglQueryString(idpy, EGL_EXTENSIONS);
+                    cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
             dp->disp[i].queryString.clientApi =
-                cnx->hooks->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
+                cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
 
         } else {
             LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
-                    egl_strerror(cnx->hooks->egl.eglGetError()));
+                    egl_strerror(cnx->egl.eglGetError()));
         }
     }
 
     EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
             EGLint n;
-            if (cnx->hooks->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
+            if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
                 dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
                 if (dp->disp[i].config) {
-                    if (cnx->hooks->egl.eglGetConfigs(
+                    if (cnx->egl.eglGetConfigs(
                             dp->disp[i].dpy, dp->disp[i].config, n,
                             &dp->disp[i].numConfigs))
                     {
@@ -742,12 +747,12 @@
         return EGL_TRUE;
 
     EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
-            if (cnx->hooks->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
+            if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
                 LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
-                        egl_strerror(cnx->hooks->egl.eglGetError()));
+                        egl_strerror(cnx->egl.eglGetError()));
             }
             // REVISIT: it's unclear what to do if eglTerminate() fails
             free(dp->disp[i].config);
@@ -784,7 +789,7 @@
         return EGL_TRUE;
     }
     GLint n = 0;
-    for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) {
+    for (int j=0 ; j<IMPL_NUM_IMPLEMENTATIONS ; j++) {
         for (int i=0 ; i<dp->disp[j].numConfigs && config_size ; i++) {
             *configs++ = MAKE_CONFIG(j, i);
             config_size--;
@@ -841,7 +846,7 @@
         
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            cnx->hooks->egl.eglGetConfigAttrib(
+            cnx->egl.eglGetConfigAttrib(
                     dp->disp[i].dpy, dp->disp[i].config[index], 
                     EGL_CONFIG_ID, &configId);
 
@@ -851,12 +856,12 @@
             // At this point, the only configuration that can match is
             // dp->configs[i][index], however, we don't know if it would be
             // rejected because of the other attributes, so we do have to call
-            // cnx->hooks->egl.eglChooseConfig() -- but we don't have to loop
+            // cnx->egl.eglChooseConfig() -- but we don't have to loop
             // through all the EGLimpl[].
             // We also know we can only get a single config back, and we know
             // which one.
 
-            res = cnx->hooks->egl.eglChooseConfig(
+            res = cnx->egl.eglChooseConfig(
                     dp->disp[i].dpy, attrib_list, configs, config_size, &n);
             if (res && n>0) {
                 // n has to be 0 or 1, by construction, and we already know
@@ -872,10 +877,10 @@
         return res;
     }
 
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglChooseConfig(
+            if (cnx->egl.eglChooseConfig(
                     dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
                 if (configs) {
                     // now we need to convert these client EGLConfig to our
@@ -917,7 +922,7 @@
         *value = configToUniqueId(dp, i, index);
         return EGL_TRUE;
     }
-    return cnx->hooks->egl.eglGetConfigAttrib(
+    return cnx->egl.eglGetConfigAttrib(
             dp->disp[i].dpy, dp->disp[i].config[index], attribute, value);
 }
 
@@ -933,7 +938,7 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface(
+        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
                 dp->disp[i].dpy, dp->disp[i].config[index], window, attrib_list);       
         if (surface != EGL_NO_SURFACE) {
             egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
@@ -951,7 +956,7 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface(
+        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
                 dp->disp[i].dpy, dp->disp[i].config[index], pixmap, attrib_list);
         if (surface != EGL_NO_SURFACE) {
             egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
@@ -968,7 +973,7 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface(
+        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
                 dp->disp[i].dpy, dp->disp[i].config[index], attrib_list);
         if (surface != EGL_NO_SURFACE) {
             egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
@@ -988,7 +993,7 @@
     egl_display_t const * const dp = get_display(dpy);
 
     egl_surface_t * const s = get_surface(surface);
-    EGLBoolean result = s->cnx->hooks->egl.eglDestroySurface(
+    EGLBoolean result = s->cnx->egl.eglDestroySurface(
             dp->disp[s->impl].dpy, s->surface);
     if (result == EGL_TRUE) {
         _s.terminate();
@@ -1007,7 +1012,7 @@
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
 
-    return s->cnx->hooks->egl.eglQuerySurface(
+    return s->cnx->egl.eglQuerySurface(
             dp->disp[s->impl].dpy, s->surface, attribute, value);
 }
 
@@ -1022,11 +1027,26 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLContext context = cnx->hooks->egl.eglCreateContext(
+        EGLContext context = cnx->egl.eglCreateContext(
                 dp->disp[i].dpy, dp->disp[i].config[index],
                 share_list, attrib_list);
         if (context != EGL_NO_CONTEXT) {
-            egl_context_t* c = new egl_context_t(dpy, context, i, cnx);
+            // figure out if it's a GLESv1 or GLESv2
+            int version = 0;
+            if (attrib_list) {
+                while (*attrib_list != EGL_NONE) {
+                    GLint attr = *attrib_list++;
+                    GLint value = *attrib_list++;
+                    if (attr == EGL_CONTEXT_CLIENT_VERSION) {
+                        if (value == 1) {
+                            version = GLESv1_INDEX;
+                        } else if (value == 2) {
+                            version = GLESv2_INDEX;
+                        }
+                    }
+                };
+            }
+            egl_context_t* c = new egl_context_t(dpy, context, i, cnx, version);
             return c;
         }
     }
@@ -1042,7 +1062,7 @@
         return EGL_FALSE;
     egl_display_t const * const dp = get_display(dpy);
     egl_context_t * const c = get_context(ctx);
-    EGLBoolean result = c->cnx->hooks->egl.eglDestroyContext(
+    EGLBoolean result = c->cnx->egl.eglDestroyContext(
             dp->disp[c->impl].dpy, c->context);
     if (result == EGL_TRUE) {
         _c.terminate();
@@ -1122,10 +1142,10 @@
     EGLBoolean result;
 
     if (c) {
-        result = c->cnx->hooks->egl.eglMakeCurrent(
+        result = c->cnx->egl.eglMakeCurrent(
                 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
     } else {
-        result = cur_c->cnx->hooks->egl.eglMakeCurrent(
+        result = cur_c->cnx->egl.eglMakeCurrent(
                 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
     }
 
@@ -1138,11 +1158,11 @@
 
         // cur_c has to be valid here (but could be terminated)
         if (ctx != EGL_NO_CONTEXT) {
-            setGlThreadSpecific(c->cnx->hooks);
+            setGlThreadSpecific(c->cnx->hooks[c->version]);
             setContext(ctx);
             _c.acquire();
         } else {
-            setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
+            setGlThreadSpecific(&gHooksNoContext);
             setContext(EGL_NO_CONTEXT);
         }
         _cur_c.release();
@@ -1171,7 +1191,7 @@
     egl_display_t const * const dp = get_display(dpy);
     egl_context_t * const c = get_context(ctx);
 
-    return c->cnx->hooks->egl.eglQueryContext(
+    return c->cnx->egl.eglQueryContext(
             dp->disp[c->impl].dpy, c->context, attribute, value);
 }
 
@@ -1231,7 +1251,7 @@
         egl_connection_t* const cnx = &gEGLImpl[c->impl];
         if (!cnx->dso) 
             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        res = cnx->hooks->egl.eglWaitGL();
+        res = cnx->egl.eglWaitGL();
     }
     return res;
 }
@@ -1251,7 +1271,7 @@
         egl_connection_t* const cnx = &gEGLImpl[c->impl];
         if (!cnx->dso) 
             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        res = cnx->hooks->egl.eglWaitNative(engine);
+        res = cnx->egl.eglWaitNative(engine);
     }
     return res;
 }
@@ -1259,11 +1279,11 @@
 EGLint eglGetError(void)
 {
     EGLint result = EGL_SUCCESS;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         EGLint err = EGL_SUCCESS;
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso)
-            err = cnx->hooks->egl.eglGetError();
+            err = cnx->egl.eglGetError();
         if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
             result = err;
     }
@@ -1294,11 +1314,11 @@
     
     addr = 0;
     int slot = -1;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglGetProcAddress) {
-                addr = cnx->hooks->egl.eglGetProcAddress(procname);
+            if (cnx->egl.eglGetProcAddress) {
+                addr = cnx->egl.eglGetProcAddress(procname);
                 if (addr) {
                     if (slot == -1) {
                         slot = 0; // XXX: find free slot
@@ -1307,7 +1327,7 @@
                             break;
                         }
                     }
-                    cnx->hooks->ext.extensions[slot] = addr;
+                    //cnx->hooks->ext.extensions[slot] = addr;
                 }
             }
         }
@@ -1347,7 +1367,7 @@
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(draw);
-    return s->cnx->hooks->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
+    return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
 }
 
 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
@@ -1360,7 +1380,7 @@
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
-    return s->cnx->hooks->egl.eglCopyBuffers(
+    return s->cnx->egl.eglCopyBuffers(
             dp->disp[s->impl].dpy, s->surface, target);
 }
 
@@ -1395,8 +1415,8 @@
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->hooks->egl.eglSurfaceAttrib) {
-        return s->cnx->hooks->egl.eglSurfaceAttrib(
+    if (s->cnx->egl.eglSurfaceAttrib) {
+        return s->cnx->egl.eglSurfaceAttrib(
                 dp->disp[s->impl].dpy, s->surface, attribute, value);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
@@ -1412,8 +1432,8 @@
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->hooks->egl.eglBindTexImage) {
-        return s->cnx->hooks->egl.eglBindTexImage(
+    if (s->cnx->egl.eglBindTexImage) {
+        return s->cnx->egl.eglBindTexImage(
                 dp->disp[s->impl].dpy, s->surface, buffer);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
@@ -1429,8 +1449,8 @@
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->hooks->egl.eglReleaseTexImage) {
-        return s->cnx->hooks->egl.eglReleaseTexImage(
+    if (s->cnx->egl.eglReleaseTexImage) {
+        return s->cnx->egl.eglReleaseTexImage(
                 dp->disp[s->impl].dpy, s->surface, buffer);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
@@ -1442,11 +1462,11 @@
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
     EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglSwapInterval) {
-                if (cnx->hooks->egl.eglSwapInterval(
+            if (cnx->egl.eglSwapInterval) {
+                if (cnx->egl.eglSwapInterval(
                         dp->disp[i].dpy, interval) == EGL_FALSE) {
                     res = EGL_FALSE;
                 }
@@ -1475,10 +1495,10 @@
         egl_connection_t* const cnx = &gEGLImpl[c->impl];
         if (!cnx->dso) 
             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (cnx->hooks->egl.eglWaitClient) {
-            res = cnx->hooks->egl.eglWaitClient();
+        if (cnx->egl.eglWaitClient) {
+            res = cnx->egl.eglWaitClient();
         } else {
-            res = cnx->hooks->egl.eglWaitGL();
+            res = cnx->egl.eglWaitGL();
         }
     }
     return res;
@@ -1492,11 +1512,11 @@
 
     // bind this API on all EGLs
     EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglBindAPI) {
-                if (cnx->hooks->egl.eglBindAPI(api) == EGL_FALSE) {
+            if (cnx->egl.eglBindAPI) {
+                if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
                     res = EGL_FALSE;
                 }
             }
@@ -1511,13 +1531,13 @@
         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
     }
 
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglQueryAPI) {
+            if (cnx->egl.eglQueryAPI) {
                 // the first one we find is okay, because they all
                 // should be the same
-                return cnx->hooks->egl.eglQueryAPI();
+                return cnx->egl.eglQueryAPI();
             }
         }
     }
@@ -1527,11 +1547,11 @@
 
 EGLBoolean eglReleaseThread(void)
 {
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglReleaseThread) {
-                cnx->hooks->egl.eglReleaseThread();
+            if (cnx->egl.eglReleaseThread) {
+                cnx->egl.eglReleaseThread();
             }
         }
     }
@@ -1547,8 +1567,8 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (!cnx) return EGL_FALSE;
-    if (cnx->hooks->egl.eglCreatePbufferFromClientBuffer) {
-        return cnx->hooks->egl.eglCreatePbufferFromClientBuffer(
+    if (cnx->egl.eglCreatePbufferFromClientBuffer) {
+        return cnx->egl.eglCreatePbufferFromClientBuffer(
                 dp->disp[i].dpy, buftype, buffer, 
                 dp->disp[i].config[index], attrib_list);
     }
@@ -1571,8 +1591,8 @@
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
 
-    if (s->cnx->hooks->egl.eglLockSurfaceKHR) {
-        return s->cnx->hooks->egl.eglLockSurfaceKHR(
+    if (s->cnx->egl.eglLockSurfaceKHR) {
+        return s->cnx->egl.eglLockSurfaceKHR(
                 dp->disp[s->impl].dpy, s->surface, attrib_list);
     }
     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -1589,8 +1609,8 @@
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
 
-    if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) {
-        return s->cnx->hooks->egl.eglUnlockSurfaceKHR(
+    if (s->cnx->egl.eglUnlockSurfaceKHR) {
+        return s->cnx->egl.eglUnlockSurfaceKHR(
                 dp->disp[s->impl].dpy, s->surface);
     }
     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -1607,7 +1627,7 @@
         egl_display_t const * const dp = get_display(dpy);
         egl_context_t * const c = get_context(ctx);
         // since we have an EGLContext, we know which implementation to use
-        EGLImageKHR image = c->cnx->hooks->egl.eglCreateImageKHR(
+        EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
                 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
         if (image == EGL_NO_IMAGE_KHR)
             return image;
@@ -1624,14 +1644,14 @@
         // since we don't have a way to know which implementation to call,
         // we're calling all of them
 
-        EGLImageKHR implImages[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+        EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
         bool success = false;
-        for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+        for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
             egl_connection_t* const cnx = &gEGLImpl[i];
             implImages[i] = EGL_NO_IMAGE_KHR;
             if (cnx->dso) {
-                if (cnx->hooks->egl.eglCreateImageKHR) {
-                    implImages[i] = cnx->hooks->egl.eglCreateImageKHR(
+                if (cnx->egl.eglCreateImageKHR) {
+                    implImages[i] = cnx->egl.eglCreateImageKHR(
                             dp->disp[i].dpy, ctx, target, buffer, attrib_list);
                     if (implImages[i] != EGL_NO_IMAGE_KHR) {
                         success = true;
@@ -1660,12 +1680,12 @@
 
      egl_image_t* image = get_image(img);
      bool success = false;
-     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
          egl_connection_t* const cnx = &gEGLImpl[i];
          if (image->images[i] != EGL_NO_IMAGE_KHR) {
              if (cnx->dso) {
-                 if (cnx->hooks->egl.eglCreateImageKHR) {
-                     if (cnx->hooks->egl.eglDestroyImageKHR(
+                 if (cnx->egl.eglCreateImageKHR) {
+                     if (cnx->egl.eglDestroyImageKHR(
                              dp->disp[i].dpy, image->images[i])) {
                          success = true;
                      }
@@ -1696,8 +1716,8 @@
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(draw);
-    if (s->cnx->hooks->egl.eglSetSwapRectangleANDROID) {
-        return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(
+    if (s->cnx->egl.eglSetSwapRectangleANDROID) {
+        return s->cnx->egl.eglSetSwapRectangleANDROID(
                 dp->disp[s->impl].dpy, s->surface, left, top, width, height);
     }
     return setError(EGL_BAD_DISPLAY, NULL);
@@ -1712,8 +1732,8 @@
         return 0;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(draw);
-    if (s->cnx->hooks->egl.eglGetRenderBufferANDROID) {
-        return s->cnx->hooks->egl.eglGetRenderBufferANDROID(
+    if (s->cnx->egl.eglGetRenderBufferANDROID) {
+        return s->cnx->egl.eglGetRenderBufferANDROID(
                 dp->disp[s->impl].dpy, s->surface);
     }
     return setError(EGL_BAD_DISPLAY, (EGLClientBuffer*)0);
diff --git a/opengl/libs/EGL/hooks.cpp b/opengl/libs/EGL/hooks.cpp
index 2246366..72ad6b3 100644
--- a/opengl/libs/EGL/hooks.cpp
+++ b/opengl/libs/EGL/hooks.cpp
@@ -41,14 +41,7 @@
 #define EGL_ENTRY(_r, _api, ...) #_api,
 
 char const * const gl_names[] = {
-    #include "GLES_CM/gl_entries.in"
-    #include "GLES_CM/glext_entries.in"
-    NULL
-};
-
-char const * const gl2_names[] = {
-    #include "GLES2/gl2_entries.in"
-    #include "GLES2/gl2ext_entries.in"
+    #include "entries.in"
     NULL
 };
 
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index e5358c3..b8e3283 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -41,22 +41,30 @@
 
 #if USE_FAST_TLS_KEY
 
+    #ifdef HAVE_ARM_TLS_REGISTER
+        #define GET_TLS(reg) \
+            "mrc p15, 0, " #reg ", c13, c0, 3 \n"
+    #else
+        #define GET_TLS(reg) \
+            "mov   " #reg ", #0xFFFF0FFF      \n"  \
+            "ldr   " #reg ", [" #reg ", #-15] \n"
+    #endif
+
     #define API_ENTRY(_api) __attribute__((naked)) _api
 
     #define CALL_GL_API(_api, ...)                              \
          asm volatile(                                          \
-            "mov   r12, #0xFFFF0FFF   \n"                       \
-            "ldr   r12, [r12, #-15]   \n"                       \
+            GET_TLS(r12)                                        \
             "ldr   r12, [r12, %[tls]] \n"                       \
             "cmp   r12, #0            \n"                       \
             "ldrne pc,  [r12, %[api]] \n"                       \
             "bx    lr                 \n"                       \
             :                                                   \
             : [tls] "J"(TLS_SLOT_OPENGL_API*4),                 \
-              [api] "J"(__builtin_offsetof(gl_hooks_t, gl2._api))    \
+              [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \
             :                                                   \
             );
-    
+
     #define CALL_GL_API_RETURN(_api, ...) \
         CALL_GL_API(_api, __VA_ARGS__) \
         return 0; // placate gcc's warnings. never reached.
@@ -66,11 +74,11 @@
     #define API_ENTRY(_api) _api
 
     #define CALL_GL_API(_api, ...)                                       \
-        gl_hooks_t::gl2_t const * const _c = &getGlThreadSpecific()->gl2; \
+        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         _c->_api(__VA_ARGS__)
     
     #define CALL_GL_API_RETURN(_api, ...)                                \
-        gl_hooks_t::gl2_t const * const _c = &getGlThreadSpecific()->gl2; \
+        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         return _c->_api(__VA_ARGS__)
 
 #endif
diff --git a/opengl/libs/GLES2/gl2_entries.in b/opengl/libs/GLES2/gl2_entries.in
deleted file mode 100644
index 6a41b94..0000000
--- a/opengl/libs/GLES2/gl2_entries.in
+++ /dev/null
@@ -1,142 +0,0 @@
-GL_ENTRY(void, glActiveTexture, GLenum texture)
-GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
-GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const char* name)
-GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
-GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
-GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)
-GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
-GL_ENTRY(void, glBlendColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-GL_ENTRY(void, glBlendEquation,  GLenum mode )
-GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha)
-GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
-GL_ENTRY(void, glBlendFuncSeparate, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
-GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const void* data, GLenum usage)
-GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void* data)
-GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target)
-GL_ENTRY(void, glClear, GLbitfield mask)
-GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-GL_ENTRY(void, glClearDepthf, GLclampf depth)
-GL_ENTRY(void, glClearStencil, GLint s)
-GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
-GL_ENTRY(void, glCompileShader, GLuint shader)
-GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
-GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
-GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
-GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(GLuint, glCreateProgram, void)
-GL_ENTRY(GLuint, glCreateShader, GLenum type)
-GL_ENTRY(void, glCullFace, GLenum mode)
-GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint* buffers)
-GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint* framebuffers)
-GL_ENTRY(void, glDeleteProgram, GLuint program)
-GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint* renderbuffers)
-GL_ENTRY(void, glDeleteShader, GLuint shader)
-GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint* textures)
-GL_ENTRY(void, glDepthFunc, GLenum func)
-GL_ENTRY(void, glDepthMask, GLboolean flag)
-GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
-GL_ENTRY(void, glDetachShader, GLuint program, GLuint shader)
-GL_ENTRY(void, glDisable, GLenum cap)
-GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
-GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
-GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const void* indices)
-GL_ENTRY(void, glEnable, GLenum cap)
-GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
-GL_ENTRY(void, glFinish, void)
-GL_ENTRY(void, glFlush, void)
-GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
-GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
-GL_ENTRY(void, glFrontFace, GLenum mode)
-GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint* buffers)
-GL_ENTRY(void, glGenerateMipmap, GLenum target)
-GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint* framebuffers)
-GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint* renderbuffers)
-GL_ENTRY(void, glGenTextures, GLsizei n, GLuint* textures)
-GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
-GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
-GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
-GL_ENTRY(int, glGetAttribLocation, GLuint program, const char* name)
-GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean* params)
-GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint* params)
-GL_ENTRY(GLenum, glGetError, void)
-GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat* params)
-GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
-GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
-GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
-GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
-GL_ENTRY(const GLubyte*, glGetString, GLenum name)
-GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat* params)
-GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat* params)
-GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint* params)
-GL_ENTRY(int, glGetUniformLocation, GLuint program, const char* name)
-GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params)
-GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer)
-GL_ENTRY(void, glHint, GLenum target, GLenum mode)
-GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
-GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
-GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer)
-GL_ENTRY(GLboolean, glIsProgram, GLuint program)
-GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer)
-GL_ENTRY(GLboolean, glIsShader, GLuint shader)
-GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
-GL_ENTRY(void, glLineWidth, GLfloat width)
-GL_ENTRY(void, glLinkProgram, GLuint program)
-GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
-GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
-GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
-GL_ENTRY(void, glReleaseShaderCompiler, void)
-GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
-GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
-GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
-GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const char** string, const GLint* length)
-GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
-GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask)
-GL_ENTRY(void, glStencilMask, GLuint mask)
-GL_ENTRY(void, glStencilMaskSeparate, GLenum face, GLuint mask)
-GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
-GL_ENTRY(void, glStencilOpSeparate, GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
-GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat,  GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
-GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat* params)
-GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
-GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint* params)
-GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels)
-GL_ENTRY(void, glUniform1f, GLint location, GLfloat x)
-GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat* v)
-GL_ENTRY(void, glUniform1i, GLint location, GLint x)
-GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint* v)
-GL_ENTRY(void, glUniform2f, GLint location, GLfloat x, GLfloat y)
-GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat* v)
-GL_ENTRY(void, glUniform2i, GLint location, GLint x, GLint y)
-GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint* v)
-GL_ENTRY(void, glUniform3f, GLint location, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat* v)
-GL_ENTRY(void, glUniform3i, GLint location, GLint x, GLint y, GLint z)
-GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint* v)
-GL_ENTRY(void, glUniform4f, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat* v)
-GL_ENTRY(void, glUniform4i, GLint location, GLint x, GLint y, GLint z, GLint w)
-GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint* v)
-GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-GL_ENTRY(void, glUseProgram, GLuint program)
-GL_ENTRY(void, glValidateProgram, GLuint program)
-GL_ENTRY(void, glVertexAttrib1f, GLuint indx, GLfloat x)
-GL_ENTRY(void, glVertexAttrib1fv, GLuint indx, const GLfloat* values)
-GL_ENTRY(void, glVertexAttrib2f, GLuint indx, GLfloat x, GLfloat y)
-GL_ENTRY(void, glVertexAttrib2fv, GLuint indx, const GLfloat* values)
-GL_ENTRY(void, glVertexAttrib3f, GLuint indx, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glVertexAttrib3fv, GLuint indx, const GLfloat* values)
-GL_ENTRY(void, glVertexAttrib4f, GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-GL_ENTRY(void, glVertexAttrib4fv, GLuint indx, const GLfloat* values)
-GL_ENTRY(void, glVertexAttribPointer, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
-GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
diff --git a/opengl/libs/GLES2/gl2ext_entries.in b/opengl/libs/GLES2/gl2ext_entries.in
deleted file mode 100644
index e608f5d..0000000
--- a/opengl/libs/GLES2/gl2ext_entries.in
+++ /dev/null
@@ -1,35 +0,0 @@
-GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
-GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
-GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
-GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length)
-GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
-GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
-GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
-GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels)
-GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels)
-GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data)
-GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data)
-GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
-GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups)
-GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
-GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, char *groupString)
-GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString)
-GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, void *data)
-GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors)
-GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint *monitors)
-GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList)
-GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)
-GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor)
-GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
-GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences)
-GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences)
-GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence)
-GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence)
-GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
-GL_ENTRY(void, glFinishFenceNV, GLuint fence)
-GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
-GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
-GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString)
-GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
-GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 1e4c136..0c9352e 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -76,12 +76,20 @@
 
 #if USE_FAST_TLS_KEY && !CHECK_FOR_GL_ERRORS
 
+    #ifdef HAVE_ARM_TLS_REGISTER
+        #define GET_TLS(reg) \
+            "mrc p15, 0, " #reg ", c13, c0, 3 \n"
+    #else
+        #define GET_TLS(reg) \
+            "mov   " #reg ", #0xFFFF0FFF      \n"  \
+            "ldr   " #reg ", [" #reg ", #-15] \n"
+    #endif
+
     #define API_ENTRY(_api) __attribute__((naked)) _api
 
     #define CALL_GL_API(_api, ...)                              \
          asm volatile(                                          \
-            "mov   r12, #0xFFFF0FFF   \n"                       \
-            "ldr   r12, [r12, #-15]   \n"                       \
+            GET_TLS(r12)                                        \
             "ldr   r12, [r12, %[tls]] \n"                       \
             "cmp   r12, #0            \n"                       \
             "ldrne pc,  [r12, %[api]] \n"                       \
@@ -91,7 +99,7 @@
               [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \
             :                                                   \
             );
-    
+
     #define CALL_GL_API_RETURN(_api, ...) \
         CALL_GL_API(_api, __VA_ARGS__) \
         return 0; // placate gcc's warnings. never reached.
diff --git a/opengl/libs/GLES_CM/gl_entries.in b/opengl/libs/GLES_CM/gl_entries.in
deleted file mode 100644
index d7cc5da..0000000
--- a/opengl/libs/GLES_CM/gl_entries.in
+++ /dev/null
@@ -1,145 +0,0 @@
-GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
-GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-GL_ENTRY(void, glClearDepthf, GLclampf depth)
-GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation)
-GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
-GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
-GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glFrustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4])
-GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
-GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glLineWidth, GLfloat width)
-GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
-GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
-GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
-GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
-GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
-GL_ENTRY(void, glOrthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glPointSize, GLfloat size)
-GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
-GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glActiveTexture, GLenum texture)
-GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
-GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
-GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
-GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
-GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
-GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
-GL_ENTRY(void, glClear, GLbitfield mask)
-GL_ENTRY(void, glClearColorx, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
-GL_ENTRY(void, glClearDepthx, GLclampx depth)
-GL_ENTRY(void, glClearStencil, GLint s)
-GL_ENTRY(void, glClientActiveTexture, GLenum texture)
-GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
-GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
-GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
-GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
-GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
-GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
-GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
-GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glCullFace, GLenum mode)
-GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
-GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
-GL_ENTRY(void, glDepthFunc, GLenum func)
-GL_ENTRY(void, glDepthMask, GLboolean flag)
-GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
-GL_ENTRY(void, glDisable, GLenum cap)
-GL_ENTRY(void, glDisableClientState, GLenum array)
-GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
-GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
-GL_ENTRY(void, glEnable, GLenum cap)
-GL_ENTRY(void, glEnableClientState, GLenum array)
-GL_ENTRY(void, glFinish, void)
-GL_ENTRY(void, glFlush, void)
-GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
-GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glFrontFace, GLenum mode)
-GL_ENTRY(void, glFrustumx, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params)
-GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4])
-GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
-GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
-GL_ENTRY(GLenum, glGetError, void)
-GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
-GL_ENTRY(const GLubyte *, glGetString, GLenum name)
-GL_ENTRY(void, glGetTexEnviv, GLenum env, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetTexEnvxv, GLenum env, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glHint, GLenum target, GLenum mode)
-GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
-GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
-GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
-GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLineWidthx, GLfixed width)
-GL_ENTRY(void, glLoadIdentity, void)
-GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
-GL_ENTRY(void, glLogicOp, GLenum opcode)
-GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
-GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glMatrixMode, GLenum mode)
-GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
-GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
-GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
-GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glOrthox, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
-GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
-GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glPointSizex, GLfixed size)
-GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
-GL_ENTRY(void, glPopMatrix, void)
-GL_ENTRY(void, glPushMatrix, void)
-GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
-GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
-GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
-GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glShadeModel, GLenum mode)
-GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
-GL_ENTRY(void, glStencilMask, GLuint mask)
-GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
-GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
-GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
-GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
-GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
-GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
-GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
-GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid *pointer)
diff --git a/opengl/libs/GLES_CM/glext_entries.in b/opengl/libs/GLES_CM/glext_entries.in
deleted file mode 100644
index dd09c71..0000000
--- a/opengl/libs/GLES_CM/glext_entries.in
+++ /dev/null
@@ -1,90 +0,0 @@
-GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
-GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
-GL_ENTRY(void, glBlendEquationOES, GLenum mode)
-GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
-GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
-GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
-GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
-GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
-GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
-GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
-GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
-GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
-GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
-GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref)
-GL_ENTRY(void, glClearColorxOES, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
-GL_ENTRY(void, glClearDepthxOES, GLclampx depth)
-GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
-GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
-GL_ENTRY(void, glDepthRangexOES, GLclampx zNear, GLclampx zFar)
-GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glFrustumxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4])
-GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetTexEnvxvOES, GLenum env, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLineWidthxOES, GLfixed width)
-GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
-GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
-GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
-GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
-GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
-GL_ENTRY(void, glOrthoxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glPointSizexOES, GLfixed size)
-GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
-GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
-GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
-GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
-GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers)
-GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers)
-GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
-GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params)
-GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
-GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
-GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint* framebuffers)
-GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint* framebuffers)
-GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
-GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
-GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
-GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint* params)
-GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
-GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
-GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
-GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
-GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
-GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
-GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16])
-GL_ENTRY(void, glDepthRangefOES, GLclampf zNear, GLclampf zFar)
-GL_ENTRY(void, glFrustumfOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glOrthofOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
-GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4])
-GL_ENTRY(void, glClearDepthfOES, GLclampf depth)
-GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
-GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
-GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index ac286cb..1fba209f7 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -23,18 +23,19 @@
 #include <EGL/eglext.h>
 #include <EGL/eglplatform.h>
 
+#include "hooks.h"
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
-struct gl_hooks_t;
-
 struct egl_connection_t
 {
     void *              dso;
-    gl_hooks_t *        hooks;
+    gl_hooks_t *        hooks[2];
     EGLint              major;
     EGLint              minor;
+    egl_t               egl;
 };
 
 EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
diff --git a/opengl/libs/entries.in b/opengl/libs/entries.in
new file mode 100644
index 0000000..bbe3e23
--- /dev/null
+++ b/opengl/libs/entries.in
@@ -0,0 +1,349 @@
+GL_ENTRY(void, glActiveTexture, GLenum texture)
+GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
+GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
+GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref)
+GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const char* name)
+GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
+GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
+GL_ENTRY(void, glBlendColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glBlendEquation,  GLenum mode )
+GL_ENTRY(void, glBlendEquationOES, GLenum mode)
+GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
+GL_ENTRY(void, glBlendFuncSeparate, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
+GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
+GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target)
+GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
+GL_ENTRY(void, glClear, GLbitfield mask)
+GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glClearColorx, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearColorxOES, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearDepthf, GLclampf depth)
+GL_ENTRY(void, glClearDepthfOES, GLclampf depth)
+GL_ENTRY(void, glClearDepthx, GLclampx depth)
+GL_ENTRY(void, glClearDepthxOES, GLclampx depth)
+GL_ENTRY(void, glClearStencil, GLint s)
+GL_ENTRY(void, glClientActiveTexture, GLenum texture)
+GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
+GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glCompileShader, GLuint shader)
+GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(GLuint, glCreateProgram, void)
+GL_ENTRY(GLuint, glCreateShader, GLenum type)
+GL_ENTRY(void, glCullFace, GLenum mode)
+GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
+GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
+GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences)
+GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glDeleteProgram, GLuint program)
+GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteShader, GLuint shader)
+GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
+GL_ENTRY(void, glDepthFunc, GLenum func)
+GL_ENTRY(void, glDepthMask, GLboolean flag)
+GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDepthRangefOES, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDepthRangexOES, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDetachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glDisable, GLenum cap)
+GL_ENTRY(void, glDisableClientState, GLenum array)
+GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
+GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
+GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
+GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
+GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
+GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
+GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
+GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
+GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
+GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
+GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEnable, GLenum cap)
+GL_ENTRY(void, glEnableClientState, GLenum array)
+GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glFinish, void)
+GL_ENTRY(void, glFinishFenceNV, GLuint fence)
+GL_ENTRY(void, glFlush, void)
+GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+GL_ENTRY(void, glFrontFace, GLenum mode)
+GL_ENTRY(void, glFrustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glFrustumfOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glFrustumx, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glFrustumxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
+GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences)
+GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
+GL_ENTRY(void, glGenerateMipmap, GLenum target)
+GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
+GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+GL_ENTRY(int, glGetAttribLocation, GLuint program, const char* name)
+GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params)
+GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
+GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString)
+GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
+GL_ENTRY(GLenum, glGetError, void)
+GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
+GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, void *data)
+GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString)
+GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
+GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, char *groupString)
+GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups)
+GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
+GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
+GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
+GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
+GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
+GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint* params)
+GL_ENTRY(const GLubyte *, glGetString, GLenum name)
+GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexEnviv, GLenum env, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexEnvxv, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexEnvxvOES, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(int, glGetUniformLocation, GLuint program, const char* name)
+GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat* params)
+GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint* params)
+GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer)
+GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params)
+GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint* params)
+GL_ENTRY(void, glHint, GLenum target, GLenum mode)
+GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
+GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
+GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence)
+GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsProgram, GLuint program)
+GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsShader, GLuint shader)
+GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLineWidth, GLfloat width)
+GL_ENTRY(void, glLineWidthx, GLfixed width)
+GL_ENTRY(void, glLineWidthxOES, GLfixed width)
+GL_ENTRY(void, glLinkProgram, GLuint program)
+GL_ENTRY(void, glLoadIdentity, void)
+GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
+GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
+GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
+GL_ENTRY(void, glLogicOp, GLenum opcode)
+GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
+GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
+GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glMatrixMode, GLenum mode)
+GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
+GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
+GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
+GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glOrthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthofOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthox, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glOrthoxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
+GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointSize, GLfloat size)
+GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glPointSizex, GLfixed size)
+GL_ENTRY(void, glPointSizexOES, GLfixed size)
+GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
+GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPopMatrix, void)
+GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length)
+GL_ENTRY(void, glPushMatrix, void)
+GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16])
+GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
+GL_ENTRY(void, glReleaseShaderCompiler, void)
+GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList)
+GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
+GL_ENTRY(void, glShadeModel, GLenum mode)
+GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
+GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const char** string, const GLint* length)
+GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilMask, GLuint mask)
+GL_ENTRY(void, glStencilMaskSeparate, GLenum face, GLuint mask)
+GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(void, glStencilOpSeparate, GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence)
+GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
+GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat,  GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels)
+GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
+GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels)
+GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glUniform1f, GLint location, GLfloat x)
+GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform1i, GLint location, GLint x)
+GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform2f, GLint location, GLfloat x, GLfloat y)
+GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform2i, GLint location, GLint x, GLint y)
+GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform3f, GLint location, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform3i, GLint location, GLint x, GLint y, GLint z)
+GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform4f, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform4i, GLint location, GLint x, GLint y, GLint z, GLint w)
+GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
+GL_ENTRY(void, glUseProgram, GLuint program)
+GL_ENTRY(void, glValidateProgram, GLuint program)
+GL_ENTRY(void, glVertexAttrib1f, GLuint indx, GLfloat x)
+GL_ENTRY(void, glVertexAttrib1fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib2f, GLuint indx, GLfloat x, GLfloat y)
+GL_ENTRY(void, glVertexAttrib2fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib3f, GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glVertexAttrib3fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib4f, GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glVertexAttrib4fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttribPointer, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
+GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 8c0357e..f47f093 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -60,11 +60,14 @@
 enum {
     IMPL_HARDWARE = 0,
     IMPL_SOFTWARE,
-    IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
-    IMPL_NO_CONTEXT = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
     IMPL_NUM_IMPLEMENTATIONS
 };
 
+enum {
+    GLESv1_INDEX = 0,
+    GLESv2_INDEX = 1,
+};
+
 // ----------------------------------------------------------------------------
 
 // GL / EGL hooks
@@ -74,18 +77,14 @@
 #define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);
 #define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);
 
+struct egl_t {
+    #include "EGL/egl_entries.in"
+};
+
 struct gl_hooks_t {
     struct gl_t {
-        #include "GLES_CM/gl_entries.in"
-        #include "GLES_CM/glext_entries.in"
+        #include "entries.in"
     } gl;
-    struct gl2_t {
-        #include "GLES2/gl2_entries.in"
-        #include "GLES2/gl2ext_entries.in"
-    } gl2;
-    struct egl_t {
-        #include "EGL/egl_entries.in"
-    } egl;
     struct gl_ext_t {
         void (*extensions[MAX_NUMBER_OF_GL_EXTENSIONS])(void);
     } ext;
@@ -96,12 +95,12 @@
 
 // ----------------------------------------------------------------------------
 
-extern gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS];
+extern gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+extern gl_hooks_t gHooksNoContext;
 extern pthread_key_t gGLWrapperKey;
 extern "C" void gl_unimplemented();
 
 extern char const * const gl_names[];
-extern char const * const gl2_names[];
 extern char const * const egl_names[];
 
 // ----------------------------------------------------------------------------
@@ -125,7 +124,7 @@
     gl_hooks_t const * volatile * tls_hooks = get_tls_hooks();
     gl_hooks_t const* hooks = tls_hooks[TLS_SLOT_OPENGL_API];
     if (hooks) return hooks;
-    return &gHooks[IMPL_NO_CONTEXT];
+    return &gHooksNoContext;
 }
 
 #else
@@ -137,7 +136,7 @@
 static gl_hooks_t const* getGlThreadSpecific() {
     gl_hooks_t const* hooks =  static_cast<gl_hooks_t*>(pthread_getspecific(gGLWrapperKey));
     if (hooks) return hooks;
-    return &gHooks[IMPL_NO_CONTEXT];
+    return &gHooksNoContext;
 }
 
 #endif
diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles
index 4f8eda4..120cb4b 100755
--- a/opengl/libs/tools/genfiles
+++ b/opengl/libs/tools/genfiles
@@ -14,14 +14,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-./glapigen ../../include/GLES/gl.h > ../GLES_CM/gl_api.in 
-./glentrygen ../../include/GLES/gl.h > ../GLES_CM/gl_entries.in 
+./glapigen ../../include/GLES/gl.h      > ../GLES_CM/gl_api.in
+./glapigen ../../include/GLES/glext.h   > ../GLES_CM/glext_api.in
+./glapigen ../../include/GLES2/gl2.h    > ../GLES2/gl2_api.in
+./glapigen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_api.in
 
-./glapigen ../../include/GLES/glext.h > ../GLES_CM/glext_api.in 
-./glentrygen ../../include/GLES/glext.h > ../GLES_CM/glext_entries.in 
+./glentrygen ../../include/GLES/gl.h      > /tmp/gl_entries.in
+./glentrygen ../../include/GLES/glext.h   > /tmp/glext_entries.in
+./glentrygen ../../include/GLES2/gl2.h    > /tmp/gl2_entries.in
+./glentrygen ../../include/GLES2/gl2ext.h > /tmp/gl2ext_entries.in
 
-./glapigen ../../include/GLES2/gl2.h > ../GLES2/gl2_api.in 
-./glentrygen ../../include/GLES2/gl2.h > ../GLES2/gl2_entries.in 
-
-./glapigen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_api.in 
-./glentrygen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_entries.in 
+cat /tmp/gl_entries.in \
+    /tmp/glext_entries.in \
+    /tmp/gl2_entries.in \
+    /tmp/gl2ext_entries.in \
+        | sort -t, -k2 \
+        | awk -F, '!_[$2]++' \
+            > ../entries.in
diff --git a/opengl/tests/gldual/Android.mk b/opengl/tests/gldual/Android.mk
new file mode 100644
index 0000000..e73c249
--- /dev/null
+++ b/opengl/tests/gldual/Android.mk
@@ -0,0 +1,51 @@
+#########################################################################
+# OpenGL ES JNI sample
+# This makefile builds both an activity and a shared library.
+#########################################################################
+ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
+
+TOP_LOCAL_PATH:= $(call my-dir)
+
+# Build activity
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := user
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := GLDual
+
+LOCAL_JNI_SHARED_LIBRARIES := libgldualjni
+
+include $(BUILD_PACKAGE)
+
+#########################################################################
+# Build JNI Shared Library
+#########################################################################
+
+LOCAL_PATH:= $(LOCAL_PATH)/jni
+
+include $(CLEAR_VARS)
+
+# Optional tag would mean it doesn't get installed by default
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -Werror
+
+LOCAL_SRC_FILES:= \
+  gl_code.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libutils \
+	libEGL \
+	libGLESv2
+
+LOCAL_MODULE := libgldualjni
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # TARGET_SIMULATOR
diff --git a/opengl/tests/gldual/AndroidManifest.xml b/opengl/tests/gldual/AndroidManifest.xml
new file mode 100644
index 0000000..06f4c4d
--- /dev/null
+++ b/opengl/tests/gldual/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** 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.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.gldual">
+    <application
+            android:label="@string/gldual_activity">
+        <activity android:name="GLDualActivity"
+                android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+            	android:launchMode="singleTask"
+            	android:configChanges="orientation|keyboardHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/opengl/tests/gldual/jni/gl_code.cpp b/opengl/tests/gldual/jni/gl_code.cpp
new file mode 100644
index 0000000..f1f0a1f
--- /dev/null
+++ b/opengl/tests/gldual/jni/gl_code.cpp
@@ -0,0 +1,165 @@
+// OpenGL ES 2.0 code
+
+#include <nativehelper/jni.h>
+#define LOG_TAG "GL2JNI gl_code.cpp"
+#include <utils/Log.h>
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+static void printGLString(const char *name, GLenum s) {
+    const char *v = (const char *) glGetString(s);
+    LOGI("GL %s = %s\n", name, v);
+}
+
+static void checkGlError(const char* op) {
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        LOGI("after %s() glError (0x%x)\n", op, error);
+    }
+}
+
+static const char gVertexShader[] = "attribute vec4 vPosition;\n"
+    "void main() {\n"
+    "  gl_Position = vPosition;\n"
+    "}\n";
+
+static const char gFragmentShader[] = "precision mediump float;\n"
+    "void main() {\n"
+    "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+    "}\n";
+
+GLuint loadShader(GLenum shaderType, const char* pSource) {
+    GLuint shader = glCreateShader(shaderType);
+    if (shader) {
+        glShaderSource(shader, 1, &pSource, NULL);
+        glCompileShader(shader);
+        GLint compiled = 0;
+        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+        if (!compiled) {
+            GLint infoLen = 0;
+            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+            if (infoLen) {
+                char* buf = (char*) malloc(infoLen);
+                if (buf) {
+                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
+                    LOGE("Could not compile shader %d:\n%s\n",
+                            shaderType, buf);
+                    free(buf);
+                }
+                glDeleteShader(shader);
+                shader = 0;
+            }
+        }
+    }
+    return shader;
+}
+
+GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
+    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
+    if (!vertexShader) {
+        return 0;
+    }
+
+    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
+    if (!pixelShader) {
+        return 0;
+    }
+
+    GLuint program = glCreateProgram();
+    if (program) {
+        glAttachShader(program, vertexShader);
+        checkGlError("glAttachShader");
+        glAttachShader(program, pixelShader);
+        checkGlError("glAttachShader");
+        glLinkProgram(program);
+        GLint linkStatus = GL_FALSE;
+        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+        if (linkStatus != GL_TRUE) {
+            GLint bufLength = 0;
+            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+            if (bufLength) {
+                char* buf = (char*) malloc(bufLength);
+                if (buf) {
+                    glGetProgramInfoLog(program, bufLength, NULL, buf);
+                    LOGE("Could not link program:\n%s\n", buf);
+                    free(buf);
+                }
+            }
+            glDeleteProgram(program);
+            program = 0;
+        }
+    }
+    return program;
+}
+
+GLuint gProgram;
+GLuint gvPositionHandle;
+
+bool setupGraphics(int w, int h) {
+    printGLString("Version", GL_VERSION);
+    printGLString("Vendor", GL_VENDOR);
+    printGLString("Renderer", GL_RENDERER);
+    printGLString("Extensions", GL_EXTENSIONS);
+
+    LOGI("setupGraphics(%d, %d)", w, h);
+    gProgram = createProgram(gVertexShader, gFragmentShader);
+    if (!gProgram) {
+        LOGE("Could not create program.");
+        return false;
+    }
+    gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
+    checkGlError("glGetAttribLocation");
+    LOGI("glGetAttribLocation(\"vPosition\") = %d\n",
+            gvPositionHandle);
+
+    glViewport(0, 0, w, h);
+    checkGlError("glViewport");
+    return true;
+}
+
+const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
+        0.5f, -0.5f };
+
+void renderFrame() {
+    static float grey;
+    grey += 0.01f;
+    if (grey > 1.0f) {
+        grey = 0.0f;
+    }
+    glClearColor(grey, grey, grey, 1.0f);
+    checkGlError("glClearColor");
+    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    checkGlError("glClear");
+
+    glUseProgram(gProgram);
+    checkGlError("glUseProgram");
+
+    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
+    checkGlError("glVertexAttribPointer");
+    glEnableVertexAttribArray(gvPositionHandle);
+    checkGlError("glEnableVertexAttribArray");
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+    checkGlError("glDrawArrays");
+}
+
+extern "C" {
+    JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_init(JNIEnv * env, jobject obj, jint width, jint height);
+    JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_step(JNIEnv * env, jobject obj);
+};
+
+JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_init(JNIEnv * env, jobject obj, jint width, jint height)

+{
+    setupGraphics(width, height);
+}
+
+JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_step(JNIEnv * env, jobject obj)
+{
+    renderFrame();
+}
+
diff --git a/opengl/tests/gldual/res/layout/gldual_activity.xml b/opengl/tests/gldual/res/layout/gldual_activity.xml
new file mode 100644
index 0000000..f2d59c7
--- /dev/null
+++ b/opengl/tests/gldual/res/layout/gldual_activity.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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:id="@+id/text"
+
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+  <android.opengl.GLSurfaceView android:id="@+id/gl1"
+	android:layout_width="fill_parent"
+	    android:layout_height="0dip"
+	    android:layout_weight="1" />
+  <com.android.gldual.GLDualGL2View android:id="@+id/gl2"
+	android:layout_width="fill_parent"
+            android:layout_height="0dip"
+            android:layout_weight="1" />
+</LinearLayout>
diff --git a/opengl/tests/gldual/res/values/strings.xml b/opengl/tests/gldual/res/values/strings.xml
new file mode 100644
index 0000000..4267dff
--- /dev/null
+++ b/opengl/tests/gldual/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2006, 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.
+*/
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+     them to be changed based on the locale and options. -->
+
+<resources>
+    <!-- Simple strings. -->
+    <string name="gldual_activity">GLDual</string>
+
+</resources>
+
diff --git a/opengl/tests/gldual/src/com/android/gldual/GLDualActivity.java b/opengl/tests/gldual/src/com/android/gldual/GLDualActivity.java
new file mode 100644
index 0000000..9d88f64
--- /dev/null
+++ b/opengl/tests/gldual/src/com/android/gldual/GLDualActivity.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.gldual;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.LinearLayout;
+
+
+public class GLDualActivity extends Activity {
+
+    GLSurfaceView mGLView;
+    GLDualGL2View mGL2View;
+
+    @Override protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        View root = getLayoutInflater().inflate(R.layout.gldual_activity, null);
+        mGLView = (GLSurfaceView) root.findViewById(R.id.gl1);
+        mGLView.setEGLConfigChooser(5,6,5,0,0,0);
+        mGLView.setRenderer(new TriangleRenderer());
+        mGL2View = (GLDualGL2View) root.findViewById(R.id.gl2);
+        setContentView(root);
+    }
+
+    @Override protected void onPause() {
+        super.onPause();
+        mGLView.onPause();
+        mGL2View.onPause();
+    }
+
+    @Override protected void onResume() {
+        super.onResume();
+        mGLView.onResume();
+        mGL2View.onResume();
+    }
+}
diff --git a/opengl/tests/gldual/src/com/android/gldual/GLDualGL2View.java b/opengl/tests/gldual/src/com/android/gldual/GLDualGL2View.java
new file mode 100644
index 0000000..8f5e347
--- /dev/null
+++ b/opengl/tests/gldual/src/com/android/gldual/GLDualGL2View.java
@@ -0,0 +1,299 @@
+/*
+ * 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.gldual;
+/*
+ * 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.
+ */
+
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.util.Log;
+
+/**
+ * An implementation of SurfaceView that uses the dedicated surface for
+ * displaying an OpenGL animation.  This allows the animation to run in a
+ * separate thread, without requiring that it be driven by the update mechanism
+ * of the view hierarchy.
+ *
+ * The application-specific rendering code is delegated to a GLView.Renderer
+ * instance.
+ */
+class GLDualGL2View extends GLSurfaceView {
+    private static String TAG = "GLDualGL2View";
+
+    public GLDualGL2View(Context context) {
+        super(context);
+        init(false, 0, 0);
+    }
+
+    public GLDualGL2View(Context context, AttributeSet set) {
+        super(context, set);
+        init(false, 0, 0);
+    }
+
+    public GLDualGL2View(Context context, boolean translucent, int depth, int stencil) {
+        super(context);
+        init(translucent, depth, stencil);
+    }
+
+    private void init(boolean translucent, int depth, int stencil) {
+        setEGLContextFactory(new ContextFactory());
+        setEGLConfigChooser( translucent ?
+              new ConfigChooser(8,8,8,8, depth, stencil) :
+              new ConfigChooser(5,6,5,0, depth, stencil));
+        setRenderer(new Renderer());
+    }
+
+    private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
+        private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+        public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
+            Log.w(TAG, "creating OpenGL ES 2.0 context");
+            checkEglError("Before eglCreateContext", egl);
+            int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
+            EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+            checkEglError("After eglCreateContext", egl);
+            return context;
+        }
+
+        public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
+            egl.eglDestroyContext(display, context);
+        }
+    }
+
+    private static void checkEglError(String prompt, EGL10 egl) {
+        int error;
+        while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
+            Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
+        }
+    }
+
+    private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
+        private static int EGL_OPENGL_ES2_BIT = 4;
+        private static int[] s_configAttribs2 =
+        {
+            EGL10.EGL_RED_SIZE, 4,
+            EGL10.EGL_GREEN_SIZE, 4,
+            EGL10.EGL_BLUE_SIZE, 4,
+            EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+            EGL10.EGL_NONE
+        };
+
+        public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
+            mRedSize = r;
+            mGreenSize = g;
+            mBlueSize = b;
+            mAlphaSize = a;
+            mDepthSize = depth;
+            mStencilSize = stencil;
+        }
+
+        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+
+            int[] num_config = new int[1];
+            egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
+
+            int numConfigs = num_config[0];
+
+            if (numConfigs <= 0) {
+                throw new IllegalArgumentException("No configs match configSpec");
+            }
+            EGLConfig[] configs = new EGLConfig[numConfigs];
+            egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
+            // printConfigs(egl, display, configs);
+            return chooseConfig(egl, display, configs);
+        }
+
+        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
+                EGLConfig[] configs) {
+            EGLConfig closestConfig = null;
+            int closestDistance = 1000;
+            for(EGLConfig config : configs) {
+                int d = findConfigAttrib(egl, display, config,
+                        EGL10.EGL_DEPTH_SIZE, 0);
+                int s = findConfigAttrib(egl, display, config,
+                        EGL10.EGL_STENCIL_SIZE, 0);
+                if (d >= mDepthSize && s>= mStencilSize) {
+                    int r = findConfigAttrib(egl, display, config,
+                            EGL10.EGL_RED_SIZE, 0);
+                    int g = findConfigAttrib(egl, display, config,
+                             EGL10.EGL_GREEN_SIZE, 0);
+                    int b = findConfigAttrib(egl, display, config,
+                              EGL10.EGL_BLUE_SIZE, 0);
+                    int a = findConfigAttrib(egl, display, config,
+                            EGL10.EGL_ALPHA_SIZE, 0);
+                    int distance = Math.abs(r - mRedSize)
+                                + Math.abs(g - mGreenSize)
+                                + Math.abs(b - mBlueSize)
+                                + Math.abs(a - mAlphaSize);
+                    if (distance < closestDistance) {
+                        closestDistance = distance;
+                        closestConfig = config;
+                    }
+                }
+            }
+            return closestConfig;
+        }
+
+        private int findConfigAttrib(EGL10 egl, EGLDisplay display,
+                EGLConfig config, int attribute, int defaultValue) {
+
+            if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
+                return mValue[0];
+            }
+            return defaultValue;
+        }
+
+        private void printConfigs(EGL10 egl, EGLDisplay display,
+            EGLConfig[] configs) {
+            int numConfigs = configs.length;
+            Log.w(TAG, String.format("%d configurations", numConfigs));
+            for (int i = 0; i < numConfigs; i++) {
+                Log.w(TAG, String.format("Configuration %d:\n", i));
+                printConfig(egl, display, configs[i]);
+            }
+        }
+
+        private void printConfig(EGL10 egl, EGLDisplay display,
+                EGLConfig config) {
+            int[] attributes = {
+                    EGL10.EGL_BUFFER_SIZE,
+                    EGL10.EGL_ALPHA_SIZE,
+                    EGL10.EGL_BLUE_SIZE,
+                    EGL10.EGL_GREEN_SIZE,
+                    EGL10.EGL_RED_SIZE,
+                    EGL10.EGL_DEPTH_SIZE,
+                    EGL10.EGL_STENCIL_SIZE,
+                    EGL10.EGL_CONFIG_CAVEAT,
+                    EGL10.EGL_CONFIG_ID,
+                    EGL10.EGL_LEVEL,
+                    EGL10.EGL_MAX_PBUFFER_HEIGHT,
+                    EGL10.EGL_MAX_PBUFFER_PIXELS,
+                    EGL10.EGL_MAX_PBUFFER_WIDTH,
+                    EGL10.EGL_NATIVE_RENDERABLE,
+                    EGL10.EGL_NATIVE_VISUAL_ID,
+                    EGL10.EGL_NATIVE_VISUAL_TYPE,
+                    0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
+                    EGL10.EGL_SAMPLES,
+                    EGL10.EGL_SAMPLE_BUFFERS,
+                    EGL10.EGL_SURFACE_TYPE,
+                    EGL10.EGL_TRANSPARENT_TYPE,
+                    EGL10.EGL_TRANSPARENT_RED_VALUE,
+                    EGL10.EGL_TRANSPARENT_GREEN_VALUE,
+                    EGL10.EGL_TRANSPARENT_BLUE_VALUE,
+                    0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
+                    0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
+                    0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
+                    0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
+                    EGL10.EGL_LUMINANCE_SIZE,
+                    EGL10.EGL_ALPHA_MASK_SIZE,
+                    EGL10.EGL_COLOR_BUFFER_TYPE,
+                    EGL10.EGL_RENDERABLE_TYPE,
+                    0x3042 // EGL10.EGL_CONFORMANT
+            };
+            String[] names = {
+                    "EGL_BUFFER_SIZE",
+                    "EGL_ALPHA_SIZE",
+                    "EGL_BLUE_SIZE",
+                    "EGL_GREEN_SIZE",
+                    "EGL_RED_SIZE",
+                    "EGL_DEPTH_SIZE",
+                    "EGL_STENCIL_SIZE",
+                    "EGL_CONFIG_CAVEAT",
+                    "EGL_CONFIG_ID",
+                    "EGL_LEVEL",
+                    "EGL_MAX_PBUFFER_HEIGHT",
+                    "EGL_MAX_PBUFFER_PIXELS",
+                    "EGL_MAX_PBUFFER_WIDTH",
+                    "EGL_NATIVE_RENDERABLE",
+                    "EGL_NATIVE_VISUAL_ID",
+                    "EGL_NATIVE_VISUAL_TYPE",
+                    "EGL_PRESERVED_RESOURCES",
+                    "EGL_SAMPLES",
+                    "EGL_SAMPLE_BUFFERS",
+                    "EGL_SURFACE_TYPE",
+                    "EGL_TRANSPARENT_TYPE",
+                    "EGL_TRANSPARENT_RED_VALUE",
+                    "EGL_TRANSPARENT_GREEN_VALUE",
+                    "EGL_TRANSPARENT_BLUE_VALUE",
+                    "EGL_BIND_TO_TEXTURE_RGB",
+                    "EGL_BIND_TO_TEXTURE_RGBA",
+                    "EGL_MIN_SWAP_INTERVAL",
+                    "EGL_MAX_SWAP_INTERVAL",
+                    "EGL_LUMINANCE_SIZE",
+                    "EGL_ALPHA_MASK_SIZE",
+                    "EGL_COLOR_BUFFER_TYPE",
+                    "EGL_RENDERABLE_TYPE",
+                    "EGL_CONFORMANT"
+            };
+            int[] value = new int[1];
+            for (int i = 0; i < attributes.length; i++) {
+                int attribute = attributes[i];
+                String name = names[i];
+                if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
+                    Log.w(TAG, String.format("  %s: %d\n", name, value[0]));
+                } else {
+                    // Log.w(TAG, String.format("  %s: failed\n", name));
+                    while (egl.eglGetError() != EGL10.EGL_SUCCESS);
+                }
+            }
+        }
+
+        // Subclasses can adjust these values:
+        protected int mRedSize;
+        protected int mGreenSize;
+        protected int mBlueSize;
+        protected int mAlphaSize;
+        protected int mDepthSize;
+        protected int mStencilSize;
+        private int[] mValue = new int[1];
+    }
+
+    private static class Renderer implements GLSurfaceView.Renderer {
+        public void onDrawFrame(GL10 gl) {
+            GLDualLib.step();
+        }
+
+        public void onSurfaceChanged(GL10 gl, int width, int height) {
+            GLDualLib.init(width, height);
+        }
+
+        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+            // Do nothing.
+        }
+    }
+}
+
diff --git a/opengl/tests/gldual/src/com/android/gldual/GLDualLib.java b/opengl/tests/gldual/src/com/android/gldual/GLDualLib.java
new file mode 100644
index 0000000..d8f765e
--- /dev/null
+++ b/opengl/tests/gldual/src/com/android/gldual/GLDualLib.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.gldual;
+
+// Wrapper for native library
+
+public class GLDualLib {
+
+     static {
+         System.loadLibrary("gldualjni");
+     }
+
+    /**
+     * @param width the current view width
+     * @param height the current view height
+     */
+     public static native void init(int width, int height);
+     public static native void step();
+}
diff --git a/opengl/tests/gldual/src/com/android/gldual/TriangleRenderer.java b/opengl/tests/gldual/src/com/android/gldual/TriangleRenderer.java
new file mode 100644
index 0000000..098c4d2
--- /dev/null
+++ b/opengl/tests/gldual/src/com/android/gldual/TriangleRenderer.java
@@ -0,0 +1,149 @@
+package com.android.gldual;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.os.SystemClock;
+
+public class TriangleRenderer implements GLSurfaceView.Renderer{
+
+    public TriangleRenderer() {
+        mTriangle = new Triangle();
+    }
+
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        /*
+         * By default, OpenGL enables features that improve quality
+         * but reduce performance. One might want to tweak that
+         * especially on software renderer.
+         */
+        gl.glDisable(GL10.GL_DITHER);
+
+        /*
+         * Some one-time OpenGL initialization can be made here
+         * probably based on features of this particular context
+         */
+        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
+                GL10.GL_FASTEST);
+
+        gl.glClearColor(.5f, .5f, .5f, 1);
+        gl.glShadeModel(GL10.GL_SMOOTH);
+    }
+
+    public void onDrawFrame(GL10 gl) {
+        /*
+         * By default, OpenGL enables features that improve quality
+         * but reduce performance. One might want to tweak that
+         * especially on software renderer.
+         */
+        gl.glDisable(GL10.GL_DITHER);
+
+        /*
+         * Usually, the first thing one might want to do is to clear
+         * the screen. The most efficient way of doing this is to use
+         * glClear().
+         */
+
+        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+        /*
+         * Now we're ready to draw some 3D objects
+         */
+
+        gl.glMatrixMode(GL10.GL_MODELVIEW);
+        gl.glLoadIdentity();
+
+        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
+
+        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+
+        long time = SystemClock.uptimeMillis() % 4000L;
+        float angle = 0.090f * ((int) time);
+
+        gl.glRotatef(angle, 0, 0, 1.0f);
+
+        mTriangle.draw(gl);
+    }
+
+    public void onSurfaceChanged(GL10 gl, int w, int h) {
+        gl.glViewport(0, 0, w, h);
+
+        /*
+        * Set our projection matrix. This doesn't have to be done
+        * each time we draw, but usually a new projection needs to
+        * be set when the viewport is resized.
+        */
+
+        float ratio = (float) w / h;
+        gl.glMatrixMode(GL10.GL_PROJECTION);
+        gl.glLoadIdentity();
+        gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);
+
+    }
+
+    private Triangle mTriangle;
+}
+
+class Triangle {
+    public Triangle() {
+
+        // Buffers to be passed to gl*Pointer() functions
+        // must be direct, i.e., they must be placed on the
+        // native heap where the garbage collector cannot
+        // move them.
+        //
+        // Buffers with multi-byte datatypes (e.g., short, int, float)
+        // must have their byte order set to native order
+
+        ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 3 * 4);
+        vbb.order(ByteOrder.nativeOrder());
+        mFVertexBuffer = vbb.asFloatBuffer();
+
+        ByteBuffer tbb = ByteBuffer.allocateDirect(VERTS * 2 * 4);
+        tbb.order(ByteOrder.nativeOrder());
+
+        ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 2);
+        ibb.order(ByteOrder.nativeOrder());
+        mIndexBuffer = ibb.asShortBuffer();
+
+        // A unit-sided equalateral triangle centered on the origin.
+        float[] coords = {
+                // X, Y, Z
+                -0.5f, -0.25f, 0,
+                 0.5f, -0.25f, 0,
+                 0.0f,  0.559016994f, 0
+        };
+
+        for (int i = 0; i < VERTS; i++) {
+            for(int j = 0; j < 3; j++) {
+                mFVertexBuffer.put(coords[i*3+j] * 2.0f);
+            }
+        }
+
+        for(int i = 0; i < VERTS; i++) {
+            mIndexBuffer.put((short) i);
+        }
+
+        mFVertexBuffer.position(0);
+        mIndexBuffer.position(0);
+    }
+
+    public void draw(GL10 gl) {
+        gl.glFrontFace(GL10.GL_CCW);
+        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
+        gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, VERTS,
+                GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
+    }
+
+    private final static int VERTS = 3;
+
+    private FloatBuffer mFVertexBuffer;
+    private ShortBuffer mIndexBuffer;
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 3b91a38..153a5ea 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -45,7 +45,6 @@
 
     private boolean mSilent;
     private boolean mVibrate;
-    private boolean mHasAutoBrightness;
 
     public SettingsHelper(Context context) {
         mContext = context;
@@ -54,9 +53,6 @@
         mContentService = ContentResolver.getContentService();
         mPowerManager = IPowerManager.Stub.asInterface(
                 ServiceManager.getService("power"));
-
-        mHasAutoBrightness = context.getResources().getBoolean(
-                com.android.internal.R.bool.config_automatic_brightness_available);
     }
 
     /**
@@ -71,18 +67,6 @@
     public boolean restoreValue(String name, String value) {
         if (Settings.System.SCREEN_BRIGHTNESS.equals(name)) {
             setBrightness(Integer.parseInt(value));
-        } else if (Settings.System.SCREEN_BRIGHTNESS_MODE.equals(name)) {
-            if (mHasAutoBrightness) {
-                // When setting auto-brightness, must reset the brightness afterwards
-                try {
-                    int curBrightness = Settings.System.getInt(mContext.getContentResolver(),
-                            Settings.System.SCREEN_BRIGHTNESS);
-                    setAutoBrightness(Integer.parseInt(value) != 0);
-                    setBrightness(curBrightness);
-                } catch (Settings.SettingNotFoundException e) {
-                    // no brightness setting at all?  weird.  skip this then.
-                }
-            }
         } else if (Settings.System.SOUND_EFFECTS_ENABLED.equals(name)) {
             setSoundEffects(Integer.parseInt(value) == 1);
         } else if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
@@ -92,16 +76,6 @@
         return true;
     }
 
-    private void setAutoBrightness(boolean value) {
-        if (mPowerManager != null) {
-            try {
-                mPowerManager.setAutoBrightness(value);
-            } catch (RemoteException e) {
-                // unable to reach the power manager; skip
-            }
-        }
-    }
-
     private void setGpsLocation(String value) {
         final String GPS = LocationManager.GPS_PROVIDER;
         boolean enabled = 
diff --git a/packages/VpnServices/res/values-zh-rCN/strings.xml b/packages/VpnServices/res/values-zh-rCN/strings.xml
index 4de0f38..940e210 100644
--- a/packages/VpnServices/res/values-zh-rCN/strings.xml
+++ b/packages/VpnServices/res/values-zh-rCN/strings.xml
@@ -15,8 +15,8 @@
 -->
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN 服务"</string>
+    <string name="app_label" msgid="4589592829302498102">"虚拟专用网服务"</string>
     <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN 已连接"</string>
     <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN 连接已断开"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"触摸可重新连接 VPN。"</string>
+    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"轻触可重新连接到虚拟专用网。"</string>
 </resources>
diff --git a/services/java/com/android/server/DropBoxService.java b/services/java/com/android/server/DropBoxService.java
new file mode 100644
index 0000000..3a4c3ac
--- /dev/null
+++ b/services/java/com/android/server/DropBoxService.java
@@ -0,0 +1,725 @@
+/*
+ * 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;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.DropBoxEntry;
+import android.os.IDropBox;
+import android.os.ParcelFileDescriptor;
+import android.os.StatFs;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.text.format.DateFormat;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * Implementation of {@link IDropBox} using the filesystem.
+ *
+ * {@hide}
+ */
+public final class DropBoxService extends IDropBox.Stub {
+    private static final String TAG = "DropBoxService";
+    private static final int DEFAULT_RESERVE_PERCENT = 10;
+    private static final int DEFAULT_QUOTA_PERCENT = 10;
+    private static final int DEFAULT_QUOTA_KB = 5 * 1024;
+    private static final int DEFAULT_AGE_SECONDS = 3 * 86400;
+    private static final int QUOTA_RESCAN_MILLIS = 5000;
+
+    // TODO: This implementation currently uses one file per entry, which is
+    // inefficient for smallish entries -- consider using a single queue file
+    // per tag (or even globally) instead.
+
+    // The cached context and derived objects
+
+    private final Context mContext;
+    private final ContentResolver mContentResolver;
+    private final File mDropBoxDir;
+
+    // Accounting of all currently written log files (set in init()).
+
+    private FileList mAllFiles = null;
+    private HashMap<String, FileList> mFilesByTag = null;
+
+    // Various bits of disk information
+
+    private StatFs mStatFs = null;
+    private int mBlockSize = 0;
+    private int mCachedQuotaBlocks = 0;  // Space we can use: computed from free space, etc.
+    private long mCachedQuotaUptimeMillis = 0;
+
+    // Ensure that all log entries have a unique timestamp
+    private long mLastTimestamp = 0;
+
+    /** Receives events that might indicate a need to clean up files. */
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mCachedQuotaUptimeMillis = 0;  // Force a re-check of quota size
+            try {
+                init();
+                trimToFit();
+            } catch (IOException e) {
+                Log.e(TAG, "Can't init", e);
+            }
+        }
+    };
+
+    /**
+     * Creates an instance of managed drop box storage.  Normally there is one of these
+     * run by the system, but others can be created for testing and other purposes.
+     *
+     * @param context to use for receiving free space & gservices intents
+     * @param path to store drop box entries in
+     */
+    public DropBoxService(Context context, File path) {
+        mDropBoxDir = path;
+
+        // Set up intent receivers
+        mContext = context;
+        mContentResolver = context.getContentResolver();
+        context.registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW));
+        context.registerReceiver(mReceiver, new IntentFilter(Settings.Gservices.CHANGED_ACTION));
+
+        // The real work gets done lazily in init() -- that way service creation always
+        // succeeds, and things like disk problems cause individual method failures.
+    }
+
+    /** Unregisters broadcast receivers and any other hooks -- for test instances */
+    public void stop() {
+        mContext.unregisterReceiver(mReceiver);
+    }
+
+    public void addText(String tag, String data) {
+        addData(tag, data.getBytes(), DropBoxEntry.IS_TEXT);
+    }
+
+    public void addData(String tag, byte[] data, int flags) {
+        File temp = null;
+        OutputStream out = null;
+        try {
+            if ((flags & DropBoxEntry.IS_EMPTY) != 0) throw new IllegalArgumentException();
+
+            init();
+            if (!isTagEnabled(tag)) return;
+
+            long max = trimToFit();
+            if (data.length > max) {
+                Log.w(TAG, "Dropping: " + tag + " (" + data.length + " > " + max + " bytes)");
+                // Pass temp = null to createEntry() to leave a tombstone
+            } else {
+                temp = new File(mDropBoxDir, "drop" + Thread.currentThread().getId() + ".tmp");
+                out = new FileOutputStream(temp);
+                if (data.length > mBlockSize && ((flags & DropBoxEntry.IS_GZIPPED) == 0)) {
+                    flags = flags | DropBoxEntry.IS_GZIPPED;
+                    out = new GZIPOutputStream(out);
+                }
+                out.write(data);
+                out.close();
+                out = null;
+            }
+
+            createEntry(temp, tag, flags);
+            temp = null;
+        } catch (IOException e) {
+            Log.e(TAG, "Can't write: " + tag, e);
+        } finally {
+            try { if (out != null) out.close(); } catch (IOException e) {}
+            if (temp != null) temp.delete();
+        }
+    }
+
+    public void addFile(String tag, ParcelFileDescriptor data, int flags) {
+        File temp = null;
+        OutputStream output = null;
+        try {
+            if ((flags & DropBoxEntry.IS_EMPTY) != 0) throw new IllegalArgumentException();
+
+            init();
+            if (!isTagEnabled(tag)) return;
+            long max = trimToFit();
+            long lastTrim = System.currentTimeMillis();
+
+            byte[] buffer = new byte[mBlockSize];
+            FileInputStream input = new FileInputStream(data.getFileDescriptor());
+
+            // First, accumulate up to one block worth of data in memory before
+            // deciding whether to compress the data or not.
+
+            int read = 0;
+            while (read < buffer.length) {
+                int n = input.read(buffer, read, buffer.length - read);
+                if (n <= 0) break;
+                read += n;
+            }
+
+            // If we have at least one block, compress it -- otherwise, just write
+            // the data in uncompressed form.
+
+            temp = new File(mDropBoxDir, "drop" + Thread.currentThread().getId() + ".tmp");
+            output = new FileOutputStream(temp);
+            if (read == buffer.length && ((flags & DropBoxEntry.IS_GZIPPED) == 0)) {
+                output = new GZIPOutputStream(output);
+                flags = flags | DropBoxEntry.IS_GZIPPED;
+            }
+
+            do {
+                output.write(buffer, 0, read);
+
+                long now = System.currentTimeMillis();
+                if (now - lastTrim > 30 * 1000) {
+                    max = trimToFit();  // In case data dribbles in slowly
+                    lastTrim = now;
+                }
+
+                read = input.read(buffer);
+                if (read <= 0) {
+                    output.close();  // Get a final size measurement
+                    output = null;
+                } else {
+                    output.flush();  // So the size measurement is pseudo-reasonable
+                }
+
+                long len = temp.length();
+                if (len > max) {
+                    Log.w(TAG, "Dropping: " + tag + " (" + temp.length() + " > " + max + " bytes)");
+                    temp.delete();
+                    temp = null;  // Pass temp = null to createEntry() to leave a tombstone
+                    break;
+                }
+            } while (read > 0);
+
+            createEntry(temp, tag, flags);
+            temp = null;
+        } catch (IOException e) {
+            Log.e(TAG, "Can't write: " + tag, e);
+        } finally {
+            try { if (output != null) output.close(); } catch (IOException e) {}
+            try { data.close(); } catch (IOException e) {}
+            if (temp != null) temp.delete();
+        }
+    }
+
+    public boolean isTagEnabled(String tag) {
+        return !"disabled".equals(Settings.Gservices.getString(
+                mContentResolver, Settings.Gservices.DROPBOX_TAG_PREFIX + tag));
+    }
+
+    public synchronized DropBoxEntry getNextEntry(long millis) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.READ_LOGS)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("READ_LOGS permission required");
+        }
+
+        try {
+            init();
+        } catch (IOException e) {
+            Log.e(TAG, "Can't init", e);
+            return null;
+        }
+
+        for (EntryFile entry : mAllFiles.contents.tailSet(new EntryFile(millis + 1))) {
+            if (entry.tag == null) continue;
+            try {
+                File file = (entry.flags & DropBoxEntry.IS_EMPTY) != 0 ? null : entry.file;
+                return new DropBoxEntry(entry.tag, entry.timestampMillis, file, entry.flags);
+            } catch (IOException e) {
+                Log.e(TAG, "Can't read: " + entry.file, e);
+                // Continue to next file
+            }
+        }
+
+        return null;
+    }
+
+    public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: Can't dump DropBoxService");
+            return;
+        }
+
+        try {
+            init();
+        } catch (IOException e) {
+            pw.println("Can't initialize: " + e);
+            Log.e(TAG, "Can't init", e);
+            return;
+        }
+
+        boolean doPrint = false, doFile = false;
+        ArrayList<String> searchArgs = new ArrayList<String>();
+        for (int i = 0; args != null && i < args.length; i++) {
+            if (args[i].equals("-p") || args[i].equals("--print")) {
+                doPrint = true;
+            } else if (args[i].equals("-f") || args[i].equals("--file")) {
+                doFile = true;
+            } else if (args[i].startsWith("-")) {
+                pw.print("Unknown argument: ");
+                pw.println(args[i]);
+            } else {
+                searchArgs.add(args[i]);
+            }
+        }
+
+        pw.format("Drop box contents: %d entries", mAllFiles.contents.size());
+        pw.println();
+
+        if (!searchArgs.isEmpty()) {
+            pw.print("Searching for:");
+            for (String a : searchArgs) pw.format(" %s", a);
+            pw.println();
+        }
+
+        int numFound = 0;
+        pw.println();
+        for (EntryFile entry : mAllFiles.contents) {
+            String date = new Formatter().format("%s.%03d",
+                    DateFormat.format("yyyy-MM-dd kk:mm:ss", entry.timestampMillis),
+                    entry.timestampMillis % 1000).toString();
+
+            boolean match = true;
+            for (String a: searchArgs) match = match && (date.contains(a) || a.equals(entry.tag));
+            if (!match) continue;
+
+            numFound++;
+            pw.print(date);
+            pw.print(" ");
+            pw.print(entry.tag == null ? "(no tag)" : entry.tag);
+            if (entry.file == null) {
+                pw.println(" (no file)");
+                continue;
+            } else if ((entry.flags & DropBoxEntry.IS_EMPTY) != 0) {
+                pw.println(" (contents lost)");
+                continue;
+            } else {
+                pw.print((entry.flags & DropBoxEntry.IS_GZIPPED) != 0 ? " (comopressed " : " (");
+                pw.print((entry.flags & DropBoxEntry.IS_TEXT) != 0 ? "text" : "data");
+                pw.format(", %d bytes)", entry.file.length());
+                pw.println();
+            }
+
+            if (doFile || (doPrint && (entry.flags & DropBoxEntry.IS_TEXT) == 0)) {
+                if (!doPrint) pw.print("    ");
+                pw.println(entry.file.getPath());
+            }
+
+            if ((entry.flags & DropBoxEntry.IS_TEXT) != 0 && (doPrint || !doFile)) {
+                DropBoxEntry dbe = null;
+                try {
+                    dbe = new DropBoxEntry(
+                             entry.tag, entry.timestampMillis, entry.file, entry.flags);
+
+                    if (doPrint) {
+                        InputStreamReader r = new InputStreamReader(dbe.getInputStream());
+                        char[] buf = new char[4096];
+                        boolean newline = false;
+                        for (;;) {
+                            int n = r.read(buf);
+                            if (n <= 0) break;
+                            pw.write(buf, 0, n);
+                            newline = (buf[n - 1] == '\n');
+                        }
+                        if (!newline) pw.println();
+                    } else {
+                        String text = dbe.getText(70);
+                        boolean truncated = (text.length() == 70);
+                        pw.print("    ");
+                        pw.print(text.trim().replace('\n', '/'));
+                        if (truncated) pw.print(" ...");
+                        pw.println();
+                    }
+                } catch (IOException e) {
+                    pw.print("*** ");
+                    pw.println(e.toString());
+                    Log.e(TAG, "Can't read: " + entry.file, e);
+                } finally {
+                    if (dbe != null) dbe.close();
+                }
+            }
+
+            if (doPrint) pw.println();
+        }
+
+        if (numFound == 0) pw.println("(No entries found.)");
+
+        if (args == null || args.length == 0) {
+            if (!doPrint) pw.println();
+            pw.println("Usage: dumpsys dropbox [--print|--file] [YYYY-mm-dd] [HH:MM:SS.SSS] [tag]");
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    /** Chronologically sorted list of {@link #EntryFile} */
+    private static final class FileList implements Comparable<FileList> {
+        public int blocks = 0;
+        public final TreeSet<EntryFile> contents = new TreeSet<EntryFile>();
+
+        /** Sorts bigger FileList instances before smaller ones. */
+        public final int compareTo(FileList o) {
+            if (blocks != o.blocks) return o.blocks - blocks;
+            if (this == o) return 0;
+            if (hashCode() < o.hashCode()) return -1;
+            if (hashCode() > o.hashCode()) return 1;
+            return 0;
+        }
+    }
+
+    /** Metadata describing an on-disk log file. */
+    private static final class EntryFile implements Comparable<EntryFile> {
+        public final String tag;
+        public final long timestampMillis;
+        public final int flags;
+        public final File file;
+        public final int blocks;
+
+        /** Sorts earlier EntryFile instances before later ones. */
+        public final int compareTo(EntryFile o) {
+            if (timestampMillis < o.timestampMillis) return -1;
+            if (timestampMillis > o.timestampMillis) return 1;
+            if (file != null && o.file != null) return file.compareTo(o.file);
+            if (o.file != null) return -1;
+            if (file != null) return 1;
+            if (this == o) return 0;
+            if (hashCode() < o.hashCode()) return -1;
+            if (hashCode() > o.hashCode()) return 1;
+            return 0;
+        }
+
+        /**
+         * Moves an existing temporary file to a new log filename.
+         * @param temp file to rename
+         * @param dir to store file in
+         * @param tag to use for new log file name
+         * @param timestampMillis of log entry
+         * @param flags for the entry data (from {@link DropBoxEntry})
+         * @param blockSize to use for space accounting
+         * @throws IOException if the file can't be moved
+         */
+        public EntryFile(File temp, File dir, String tag,long timestampMillis,
+                         int flags, int blockSize) throws IOException {
+            if ((flags & DropBoxEntry.IS_EMPTY) != 0) throw new IllegalArgumentException();
+
+            this.tag = tag;
+            this.timestampMillis = timestampMillis;
+            this.flags = flags;
+            this.file = new File(dir, Uri.encode(tag) + "@" + timestampMillis +
+                    ((flags & DropBoxEntry.IS_TEXT) != 0 ? ".txt" : ".dat") +
+                    ((flags & DropBoxEntry.IS_GZIPPED) != 0 ? ".gz" : ""));
+
+            if (!temp.renameTo(this.file)) {
+                throw new IOException("Can't rename " + temp + " to " + this.file);
+            }
+            this.blocks = (int) ((this.file.length() + blockSize - 1) / blockSize);
+        }
+
+        /**
+         * Creates a zero-length tombstone for a file whose contents were lost.
+         * @param dir to store file in
+         * @param tag to use for new log file name
+         * @param timestampMillis of log entry
+         * @throws IOException if the file can't be created.
+         */
+        public EntryFile(File dir, String tag, long timestampMillis) throws IOException {
+            this.tag = tag;
+            this.timestampMillis = timestampMillis;
+            this.flags = DropBoxEntry.IS_EMPTY;
+            this.file = new File(dir, Uri.encode(tag) + "@" + timestampMillis + ".lost");
+            this.blocks = 0;
+            new FileOutputStream(this.file).close();
+        }
+
+        /**
+         * Extracts metadata from an existing on-disk log filename.
+         * @param file name of existing log file
+         * @param blockSize to use for space accounting
+         */
+        public EntryFile(File file, int blockSize) {
+            this.file = file;
+            this.blocks = (int) ((this.file.length() + blockSize - 1) / blockSize);
+
+            String name = file.getName();
+            int at = name.lastIndexOf('@');
+            if (at < 0) {
+                this.tag = null;
+                this.timestampMillis = 0;
+                this.flags = DropBoxEntry.IS_EMPTY;
+                return;
+            }
+
+            int flags = 0;
+            this.tag = Uri.decode(name.substring(0, at));
+            if (name.endsWith(".gz")) {
+                flags |= DropBoxEntry.IS_GZIPPED;
+                name = name.substring(0, name.length() - 3);
+            }
+            if (name.endsWith(".lost")) {
+                flags |= DropBoxEntry.IS_EMPTY;
+                name = name.substring(at + 1, name.length() - 5);
+            } else if (name.endsWith(".txt")) {
+                flags |= DropBoxEntry.IS_TEXT;
+                name = name.substring(at + 1, name.length() - 4);
+            } else if (name.endsWith(".dat")) {
+                name = name.substring(at + 1, name.length() - 4);
+            } else {
+                this.flags = DropBoxEntry.IS_EMPTY;
+                this.timestampMillis = 0;
+                return;
+            }
+            this.flags = flags;
+
+            long millis;
+            try { millis = Long.valueOf(name); } catch (NumberFormatException e) { millis = 0; }
+            this.timestampMillis = millis;
+        }
+
+        /**
+         * Creates a EntryFile object with only a timestamp for comparison purposes.
+         * @param timestampMillis to compare with.
+         */
+        public EntryFile(long millis) {
+            this.tag = null;
+            this.timestampMillis = millis;
+            this.flags = DropBoxEntry.IS_EMPTY;
+            this.file = null;
+            this.blocks = 0;
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    /** If never run before, scans disk contents to build in-memory tracking data. */
+    private synchronized void init() throws IOException {
+        if (mStatFs == null) {
+            if (!mDropBoxDir.isDirectory() && !mDropBoxDir.mkdirs()) {
+                throw new IOException("Can't mkdir: " + mDropBoxDir);
+            }
+            try {
+                mStatFs = new StatFs(mDropBoxDir.getPath());
+                mBlockSize = mStatFs.getBlockSize();
+            } catch (IllegalArgumentException e) {  // StatFs throws this on error
+                throw new IOException("Can't statfs: " + mDropBoxDir);
+            }
+        }
+
+        if (mAllFiles == null) {
+            File[] files = mDropBoxDir.listFiles();
+            if (files == null) throw new IOException("Can't list files: " + mDropBoxDir);
+
+            mAllFiles = new FileList();
+            mFilesByTag = new HashMap<String, FileList>();
+
+            // Scan pre-existing files.
+            for (File file : files) {
+                if (file.getName().endsWith(".tmp")) {
+                    Log.i(TAG, "Cleaning temp file: " + file);
+                    file.delete();
+                    continue;
+                }
+
+                EntryFile entry = new EntryFile(file, mBlockSize);
+                if (entry.tag == null) {
+                    Log.w(TAG, "Unrecognized file: " + file);
+                    continue;
+                } else if (entry.timestampMillis == 0) {
+                    Log.w(TAG, "Invalid filename: " + file);
+                    file.delete();
+                    continue;
+                }
+
+                enrollEntry(entry);
+            }
+        }
+    }
+
+    /** Adds a disk log file to in-memory tracking for accounting and enumeration. */
+    private synchronized void enrollEntry(EntryFile entry) {
+        mAllFiles.contents.add(entry);
+        mAllFiles.blocks += entry.blocks;
+
+        // mFilesByTag is used for trimming, so don't list empty files.
+        // (Zero-length/lost files are trimmed by date from mAllFiles.)
+
+        if (entry.tag != null && entry.file != null && entry.blocks > 0) {
+            FileList tagFiles = mFilesByTag.get(entry.tag);
+            if (tagFiles == null) {
+                tagFiles = new FileList();
+                mFilesByTag.put(entry.tag, tagFiles);
+            }
+            tagFiles.contents.add(entry);
+            tagFiles.blocks += entry.blocks;
+        }
+    }
+
+    /** Moves a temporary file to a final log filename and enrolls it. */
+    private synchronized void createEntry(File temp, String tag, int flags) throws IOException {
+        long t = System.currentTimeMillis();
+
+        // Require each entry to have a unique timestamp; if there are entries
+        // >10sec in the future (due to clock skew), drag them back to avoid
+        // keeping them around forever.
+
+        SortedSet<EntryFile> tail = mAllFiles.contents.tailSet(new EntryFile(t + 10000));
+        EntryFile[] future = null;
+        if (!tail.isEmpty()) {
+            future = tail.toArray(new EntryFile[tail.size()]);
+            tail.clear();  // Remove from mAllFiles
+        }
+
+        if (!mAllFiles.contents.isEmpty()) {
+            t = Math.max(t, mAllFiles.contents.last().timestampMillis + 1);
+        }
+
+        if (future != null) {
+            for (EntryFile late : future) {
+                mAllFiles.blocks -= late.blocks;
+                FileList tagFiles = mFilesByTag.get(late.tag);
+                if (tagFiles.contents.remove(late)) tagFiles.blocks -= late.blocks;
+                if ((late.flags & DropBoxEntry.IS_EMPTY) == 0) {
+                    enrollEntry(new EntryFile(
+                            late.file, mDropBoxDir, late.tag, t++, late.flags, mBlockSize));
+                } else {
+                    enrollEntry(new EntryFile(mDropBoxDir, late.tag, t++));
+                }
+            }
+        }
+
+        if (temp == null) {
+            enrollEntry(new EntryFile(mDropBoxDir, tag, t));
+        } else {
+            enrollEntry(new EntryFile(temp, mDropBoxDir, tag, t, flags, mBlockSize));
+        }
+    }
+
+    /**
+     * Trims the files on disk to make sure they aren't using too much space.
+     * @return the overall quota for storage (in bytes)
+     */
+    private synchronized long trimToFit() {
+        // Expunge aged items (including tombstones marking deleted data).
+
+        int ageSeconds = Settings.Gservices.getInt(mContentResolver,
+                Settings.Gservices.DROPBOX_AGE_SECONDS, DEFAULT_AGE_SECONDS);
+        long cutoffMillis = System.currentTimeMillis() - ageSeconds * 1000;
+        while (!mAllFiles.contents.isEmpty()) {
+            EntryFile entry = mAllFiles.contents.first();
+            if (entry.timestampMillis > cutoffMillis) break;
+
+            FileList tag = mFilesByTag.get(entry.tag);
+            if (tag != null && tag.contents.remove(entry)) tag.blocks -= entry.blocks;
+            if (mAllFiles.contents.remove(entry)) mAllFiles.blocks -= entry.blocks;
+            if (entry.file != null) entry.file.delete();
+        }
+
+        // Compute overall quota (a fraction of available free space) in blocks.
+        // The quota changes dynamically based on the amount of free space;
+        // that way when lots of data is available we can use it, but we'll get
+        // out of the way if storage starts getting tight.
+
+        long uptimeMillis = SystemClock.uptimeMillis();
+        if (uptimeMillis > mCachedQuotaUptimeMillis + QUOTA_RESCAN_MILLIS) {
+            int quotaPercent = Settings.Gservices.getInt(mContentResolver,
+                    Settings.Gservices.DROPBOX_QUOTA_PERCENT, DEFAULT_QUOTA_PERCENT);
+            int reservePercent = Settings.Gservices.getInt(mContentResolver,
+                    Settings.Gservices.DROPBOX_RESERVE_PERCENT, DEFAULT_RESERVE_PERCENT);
+            int quotaKb = Settings.Gservices.getInt(mContentResolver,
+                    Settings.Gservices.DROPBOX_QUOTA_KB, DEFAULT_QUOTA_KB);
+
+            mStatFs.restat(mDropBoxDir.getPath());
+            int available = mStatFs.getAvailableBlocks();
+            int nonreserved = available - mStatFs.getBlockCount() * reservePercent / 100;
+            int maximum = quotaKb * 1024 / mBlockSize;
+            mCachedQuotaBlocks = Math.min(maximum, Math.max(0, nonreserved * quotaPercent / 100));
+            mCachedQuotaUptimeMillis = uptimeMillis;
+        }
+
+        // If we're using too much space, delete old items to make room.
+        //
+        // We trim each tag independently (this is why we keep per-tag lists).
+        // Space is "fairly" shared between tags -- they are all squeezed
+        // equally until enough space is reclaimed.
+        //
+        // A single circular buffer (a la logcat) would be simpler, but this
+        // way we can handle fat/bursty data (like 1MB+ bugreports, 300KB+
+        // kernel crash dumps, and 100KB+ ANR reports) without swamping small,
+        // well-behaved data // streams (event statistics, profile data, etc).
+        //
+        // Deleted files are replaced with zero-length tombstones to mark what
+        // was lost.  Tombstones are expunged by age (see above).
+
+        if (mAllFiles.blocks > mCachedQuotaBlocks) {
+            Log.i(TAG, "Usage (" + mAllFiles.blocks + ") > Quota (" + mCachedQuotaBlocks + ")");
+
+            // Find a fair share amount of space to limit each tag
+            int unsqueezed = mAllFiles.blocks, squeezed = 0;
+            TreeSet<FileList> tags = new TreeSet<FileList>(mFilesByTag.values());
+            for (FileList tag : tags) {
+                if (squeezed > 0 && tag.blocks <= (mCachedQuotaBlocks - unsqueezed) / squeezed) {
+                    break;
+                }
+                unsqueezed -= tag.blocks;
+                squeezed++;
+            }
+            int tagQuota = (mCachedQuotaBlocks - unsqueezed) / squeezed;
+
+            // Remove old items from each tag until it meets the per-tag quota.
+            for (FileList tag : tags) {
+                if (mAllFiles.blocks < mCachedQuotaBlocks) break;
+                while (tag.blocks > tagQuota && !tag.contents.isEmpty()) {
+                    EntryFile entry = tag.contents.first();
+                    if (tag.contents.remove(entry)) tag.blocks -= entry.blocks;
+                    if (mAllFiles.contents.remove(entry)) mAllFiles.blocks -= entry.blocks;
+
+                    try {
+                        if (entry.file != null) entry.file.delete();
+                        enrollEntry(new EntryFile(mDropBoxDir, entry.tag, entry.timestampMillis));
+                    } catch (IOException e) {
+                        Log.e(TAG, "Can't write tombstone file", e);
+                    }
+                }
+            }
+        }
+
+        return mCachedQuotaBlocks * mBlockSize;
+    }
+}
diff --git a/services/java/com/android/server/HardwareService.java b/services/java/com/android/server/HardwareService.java
index 29c13e0..7c56a30 100755
--- a/services/java/com/android/server/HardwareService.java
+++ b/services/java/com/android/server/HardwareService.java
@@ -133,7 +133,7 @@
         context.registerReceiver(mIntentReceiver, filter);
 
         mAutoBrightnessAvailable = context.getResources().getBoolean(
-                com.android.internal.R.bool.config_automatic_brightness_available);
+                com.android.internal.R.bool.config_hardware_automatic_brightness_available);
     }
 
     protected void finalize() throws Throwable {
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 2dc45b5..eaad3b7 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -268,6 +268,7 @@
                 while (start != end) {
                     int soff = poff + (start*MotionEvent.NUM_SAMPLE_DATA);
                     int pressure = mHistoryData[soff + MotionEvent.SAMPLE_PRESSURE];
+                    if (pressure <= 0) pressure = 1;
                     x += mHistoryData[soff + MotionEvent.SAMPLE_X] * pressure;
                     y += mHistoryData[soff + MotionEvent.SAMPLE_Y] * pressure;
                     totalPressure += pressure;
@@ -276,6 +277,7 @@
                 }
                 int eoff = poff + (end*MotionEvent.NUM_SAMPLE_DATA);
                 int pressure = mHistoryData[eoff + MotionEvent.SAMPLE_PRESSURE];
+                if (pressure <= 0) pressure = 1;
                 x += mHistoryData[eoff + MotionEvent.SAMPLE_X] * pressure;
                 y += mHistoryData[eoff + MotionEvent.SAMPLE_Y] * pressure;
                 totalPressure += pressure;
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index 09591f4..5d65c71 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -721,11 +721,14 @@
                                         // virtual key area...  but still
                                         // propagate this to the previous
                                         // data for comparisons.
+                                        int num = ms.mNextNumPointers;
+                                        if (num > InputDevice.MAX_POINTERS) {
+                                            num = InputDevice.MAX_POINTERS;
+                                        }
                                         System.arraycopy(ms.mNextData, 0,
                                                 ms.mLastData, 0,
-                                                ms.mNextNumPointers
-                                                        * MotionEvent.NUM_SAMPLE_DATA);
-                                        ms.mLastNumPointers = ms.mNextNumPointers;
+                                                num * MotionEvent.NUM_SAMPLE_DATA);
+                                        ms.mLastNumPointers = num;
                                     }
                                     
                                     ms.finish();
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 6289d4f..66e7ecd 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -872,6 +872,10 @@
     }
 
     PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
+        if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
+            // The package has been uninstalled but has retained data and resources.
+            return PackageParser.generatePackageInfo(p, null, flags);
+        }
         final PackageSetting ps = (PackageSetting)p.mExtras;
         if (ps == null) {
             return null;
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index e1bea37..9b54a70 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -28,6 +28,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
@@ -53,6 +54,7 @@
 import static android.provider.Settings.System.DIM_SCREEN;
 import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
 import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
+import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
 import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;
 
@@ -64,7 +66,7 @@
 import java.util.Observer;
 
 class PowerManagerService extends IPowerManager.Stub
-        implements LocalPowerManager, Watchdog.Monitor, SensorEventListener {
+        implements LocalPowerManager, Watchdog.Monitor {
 
     private static final String TAG = "PowerManagerService";
     static final String PARTIAL_NAME = "PowerManagerService";
@@ -88,6 +90,9 @@
     private static final int LONG_KEYLIGHT_DELAY = 6000;        // t+6 sec
     private static final int LONG_DIM_TIME = 7000;              // t+N-5 sec
 
+    // How long to wait to debounce light sensor changes.
+    private static final int LIGHT_SENSOR_DELAY = 1000;
+
     // trigger proximity if distance is less than 5 cm
     private static final float PROXIMITY_THRESHOLD = 5.0f;
 
@@ -189,6 +194,11 @@
     private BatteryService mBatteryService;
     private SensorManager mSensorManager;
     private Sensor mProximitySensor;
+    private Sensor mLightSensor;
+    private boolean mLightSensorEnabled;
+    private float mLightSensorValue = -1;
+    private float mLightSensorPendingValue = -1;
+    private int mLightSensorBrightness = -1;
     private boolean mDimScreen = true;
     private long mNextTimeout;
     private volatile int mPokey = 0;
@@ -199,6 +209,12 @@
     private long mScreenOnStartTime;
     private boolean mPreventScreenOn;
     private int mScreenBrightnessOverride = -1;
+    private boolean mHasHardwareAutoBrightness;
+    private boolean mAutoBrightessEnabled;
+    private int[] mAutoBrightnessLevels;
+    private int[] mLcdBacklightValues;
+    private int[] mButtonBacklightValues;
+    private int[] mKeyboardBacklightValues;
 
     // Used when logging number and duration of touch-down cycles
     private long mTotalTouchDownTime;
@@ -207,6 +223,7 @@
 
     // could be either static or controllable at runtime
     private static final boolean mSpew = false;
+    private static final boolean mDebugLightSensor = false;
 
     /*
     static PrintStream mLog;
@@ -344,6 +361,9 @@
                  // DIM_SCREEN
                 //mDimScreen = getInt(DIM_SCREEN) != 0;
 
+                // SCREEN_BRIGHTNESS_MODE
+                setScreenBrightnessMode(getInt(SCREEN_BRIGHTNESS_MODE));
+
                 // recalculate everything
                 setScreenOffTimeoutsLocked();
             }
@@ -415,12 +435,28 @@
         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
         mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
 
-        ContentResolver resolver = mContext.getContentResolver();
+        Resources resources = mContext.getResources();
+        mHasHardwareAutoBrightness = resources.getBoolean(
+                com.android.internal.R.bool.config_hardware_automatic_brightness_available);
+        if (!mHasHardwareAutoBrightness) {
+            mAutoBrightnessLevels = resources.getIntArray(
+                    com.android.internal.R.array.config_autoBrightnessLevels);
+            mLcdBacklightValues = resources.getIntArray(
+                    com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
+            mButtonBacklightValues = resources.getIntArray(
+                    com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
+            mKeyboardBacklightValues = resources.getIntArray(
+                    com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);
+        }
+
+       ContentResolver resolver = mContext.getContentResolver();
         Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
                 "(" + Settings.System.NAME + "=?) or ("
                         + Settings.System.NAME + "=?) or ("
+                        + Settings.System.NAME + "=?) or ("
                         + Settings.System.NAME + "=?)",
-                new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN},
+                new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN,
+                        SCREEN_BRIGHTNESS_MODE},
                 null);
         mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
         SettingsObserver settingsObserver = new SettingsObserver();
@@ -441,12 +477,13 @@
         // And explicitly do the initial update of our cached settings
         updateGservicesValues();
 
-        // turn everything on
-        setPowerState(ALL_BRIGHT);
-
-        // set auto brightness mode to user setting
-        boolean brightnessMode = Settings.System.getInt(resolver, SCREEN_BRIGHTNESS_MODE, 1) != 0;
-        mHardware.setAutoBrightness_UNCHECKED(brightnessMode);
+        if (mAutoBrightessEnabled) {
+            // turn the screen on
+            setPowerState(SCREEN_BRIGHT);
+        } else {
+            // turn everything on
+            setPowerState(ALL_BRIGHT);
+        }
 
         synchronized (mHandlerThread) {
             mInitComplete = true;
@@ -542,7 +579,7 @@
             switch (wl.flags & LOCK_MASK)
             {
                 case PowerManager.FULL_WAKE_LOCK:
-                    wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
+                    wl.minState = SCREEN_BRIGHT;
                     break;
                 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
                     wl.minState = SCREEN_BRIGHT;
@@ -840,6 +877,12 @@
         pw.println("  mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
         pw.println("  mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
         pw.println("  mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock);
+        pw.println("  mProximitySensorActive=" + mProximitySensorActive);
+        pw.println("  mLightSensorEnabled=" + mLightSensorEnabled);
+        pw.println("  mLightSensorValue=" + mLightSensorValue);
+        pw.println("  mLightSensorPendingValue=" + mLightSensorPendingValue);
+        pw.println("  mHasHardwareAutoBrightness=" + mHasHardwareAutoBrightness);
+        pw.println("  mAutoBrightessEnabled=" + mAutoBrightessEnabled);
         mScreenBrightness.dump(pw, "  mScreenBrightness: ");
         mKeyboardBrightness.dump(pw, "  mKeyboardBrightness: ");
         mButtonBrightness.dump(pw, "  mButtonBrightness: ");
@@ -1164,7 +1207,7 @@
 
                 // Finally, set the flag that prevents the screen from turning on.
                 // (Below, in setPowerState(), we'll check mPreventScreenOn and
-                // we *won't* call Power.setScreenState(true) if it's set.)
+                // we *won't* call setScreenStateLocked(true) if it's set.)
                 mPreventScreenOn = true;
             } else {
                 // (Re)enable the screen.
@@ -1182,9 +1225,9 @@
                         Log.d(TAG,
                               "preventScreenOn: turning on after a prior preventScreenOn(true)!");
                     }
-                    int err = Power.setScreenState(true);
+                    int err = setScreenStateLocked(true);
                     if (err != 0) {
-                        Log.w(TAG, "preventScreenOn: error from Power.setScreenState(): " + err);
+                        Log.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err);
                     }
                 }
 
@@ -1239,6 +1282,22 @@
             }
         };
 
+    private int setScreenStateLocked(boolean on) {
+        int err = Power.setScreenState(on);
+        if (err == 0) {
+            enableLightSensor(on && mAutoBrightessEnabled);
+            if (!on) {
+                // make sure button and key backlights are off too
+                mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, 0);
+                mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, 0);
+                // clear current value so we will update based on the new conditions
+                // when the sensor is reenabled.
+                mLightSensorValue = -1;
+            }
+        }
+        return err;
+    }
+
     private void setPowerState(int state)
     {
         setPowerState(state, false, false);
@@ -1272,7 +1331,7 @@
                 return;
             }
             
-            if (!mDoneBooting) {
+            if (!mDoneBooting && !mAutoBrightessEnabled) {
                 newState |= ALL_BRIGHT;
             }
 
@@ -1327,7 +1386,7 @@
                         reallyTurnScreenOn = false;
                     }
                     if (reallyTurnScreenOn) {
-                        err = Power.setScreenState(true);
+                        err = setScreenStateLocked(true);
                         long identity = Binder.clearCallingIdentity();
                         try {
                             mBatteryStats.noteScreenBrightness(
@@ -1339,7 +1398,7 @@
                             Binder.restoreCallingIdentity(identity);
                         }
                     } else {
-                        Power.setScreenState(false);
+                        setScreenStateLocked(false);
                         // But continue as if we really did turn the screen on...
                         err = 0;
                     }
@@ -1384,7 +1443,7 @@
         EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, becauseOfUser ? 1 : 0,
                 mTotalTouchDownTime, mTouchCycles);
         mLastTouchDown = 0;
-        int err = Power.setScreenState(false);
+        int err = setScreenStateLocked(false);
         if (mScreenOnStartTime != 0) {
             mScreenOnTime += SystemClock.elapsedRealtime() - mScreenOnStartTime;
             mScreenOnStartTime = 0;
@@ -1693,6 +1752,8 @@
         try {
             if (mScreenBrightnessOverride >= 0) {
                 return mScreenBrightnessOverride;
+            } else if (mLightSensorBrightness >= 0) {
+                return mLightSensorBrightness;
             }
             final int brightness = Settings.System.getInt(mContext.getContentResolver(),
                                                           SCREEN_BRIGHTNESS);
@@ -1776,8 +1837,9 @@
             if (mLastEventTime <= time || force) {
                 mLastEventTime = time;
                 if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
-                    // Only turn on button backlights if a button was pressed.
-                    if (eventType == BUTTON_EVENT) {
+                    // Only turn on button backlights if a button was pressed
+                    // and auto brightness is disabled
+                    if (eventType == BUTTON_EVENT && !mAutoBrightessEnabled) {
                         mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
                     } else {
                         // don't clear button/keyboard backlights when the screen is touched.
@@ -1802,6 +1864,79 @@
         }
     }
 
+    private int getAutoBrightnessValue(int sensorValue, int[] values) {
+        try {
+            int i;
+            for (i = 0; i < mAutoBrightnessLevels.length; i++) {
+                if (sensorValue < mAutoBrightnessLevels[i]) {
+                    break;
+                }
+            }
+            return values[i];
+        } catch (Exception e) {
+            // guard against null pointer or index out of bounds errors
+            Log.e(TAG, "getAutoBrightnessValue", e);
+            return 255;
+        }
+    }
+
+    private Runnable mAutoBrightnessTask = new Runnable() {
+        public void run() {
+            synchronized (mLocks) {
+                int value = (int)mLightSensorPendingValue;
+                if (value >= 0) {
+                    mLightSensorPendingValue = -1;
+                    lightSensorChangedLocked(value);
+                }
+            }
+        }
+    };
+
+    private void lightSensorChangedLocked(int value) {
+        if (mDebugLightSensor) {
+            Log.d(TAG, "lightSensorChangedLocked " + value);
+        }
+
+        if (mLightSensorValue != value) {
+            mLightSensorValue = value;
+            if ((mPowerState & BATTERY_LOW_BIT) == 0) {
+                int lcdValue = getAutoBrightnessValue(value, mLcdBacklightValues);
+                int buttonValue = getAutoBrightnessValue(value, mButtonBacklightValues);
+                int keyboardValue = getAutoBrightnessValue(value, mKeyboardBacklightValues);
+                mLightSensorBrightness = lcdValue;
+
+                if (mDebugLightSensor) {
+                    Log.d(TAG, "lcdValue " + lcdValue);
+                    Log.d(TAG, "buttonValue " + buttonValue);
+                    Log.d(TAG, "keyboardValue " + keyboardValue);
+                }
+
+                if (mScreenBrightnessOverride < 0) {
+                    mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT,
+                            lcdValue);
+                }
+                mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS,
+                        buttonValue);
+                mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD,
+                        keyboardValue);
+
+                // update our animation state
+                if (ANIMATE_SCREEN_LIGHTS) {
+                    mScreenBrightness.curValue = lcdValue;
+                    mScreenBrightness.animating = false;
+                }
+                if (ANIMATE_BUTTON_LIGHTS) {
+                    mButtonBrightness.curValue = buttonValue;
+                    mButtonBrightness.animating = false;
+                }
+                if (ANIMATE_KEYBOARD_LIGHTS) {
+                    mKeyboardBrightness.curValue = keyboardValue;
+                    mKeyboardBrightness.animating = false;
+                }
+            }
+        }
+    }
+
     /**
      * The user requested that we go to sleep (probably with the power button).
      * This overrides all wake locks that are held.
@@ -1885,6 +2020,20 @@
         }
     }
 
+    private void setScreenBrightnessMode(int mode) {
+        mAutoBrightessEnabled = (mode == SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+        // reset computed brightness
+        mLightSensorBrightness = -1;
+
+        if (mHasHardwareAutoBrightness) {
+            // When setting auto-brightness, must reset the brightness afterwards
+            mHardware.setAutoBrightness_UNCHECKED(mAutoBrightessEnabled);
+            setBacklightBrightness((int)mScreenBrightness.curValue);
+        } else {
+            enableLightSensor(screenIsOn() && mAutoBrightessEnabled);
+        }
+    }
+
     /** Sets the screen off timeouts:
      *      mKeylightDelay
      *      mDimDelay
@@ -2031,6 +2180,14 @@
     }
     
     void systemReady() {
+        mSensorManager = new SensorManager(mHandlerThread.getLooper());
+        mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+        // don't bother with the light sensor if auto brightness is handled in hardware
+        if (!mHasHardwareAutoBrightness) {
+            mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+            enableLightSensor(mAutoBrightessEnabled);
+        }
+
         synchronized (mLocks) {
             Log.d(TAG, "system ready!");
             mDoneBooting = true;
@@ -2058,8 +2215,6 @@
                    | PowerManager.FULL_WAKE_LOCK
                    | PowerManager.SCREEN_DIM_WAKE_LOCK;
 
-        // call getSensorManager() to make sure mProximitySensor is initialized
-        getSensorManager();
         if (mProximitySensor != null) {
             result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
         }
@@ -2098,31 +2253,19 @@
         }
     }
 
-    public void setAutoBrightness(boolean on) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-        mHardware.setAutoBrightness_UNCHECKED(on);
-    }
-
-    private SensorManager getSensorManager() {
-        if (mSensorManager == null) {
-            mSensorManager = new SensorManager(mHandlerThread.getLooper());
-            mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
-        }
-        return mSensorManager;
-    }
-
     private void enableProximityLockLocked() {
         if (mSpew) {
             Log.d(TAG, "enableProximityLockLocked");
         }
-        mSensorManager.registerListener(this, mProximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
+        mSensorManager.registerListener(mProximityListener, mProximitySensor,
+                SensorManager.SENSOR_DELAY_NORMAL);
     }
 
     private void disableProximityLockLocked() {
         if (mSpew) {
             Log.d(TAG, "disableProximityLockLocked");
         }
-        mSensorManager.unregisterListener(this);
+        mSensorManager.unregisterListener(mProximityListener);
         synchronized (mLocks) {
             if (mProximitySensorActive) {
                 mProximitySensorActive = false;
@@ -2131,32 +2274,78 @@
         }
     }
 
-    public void onSensorChanged(SensorEvent event) {
-        long milliseconds = event.timestamp / 1000000;
-        synchronized (mLocks) {
-            float distance = event.values[0];
-            // compare against getMaximumRange to support sensors that only return 0 or 1
-            if (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
-                    distance < mProximitySensor.getMaximumRange()) {
-                if (mSpew) {
-                    Log.d(TAG, "onSensorChanged: proximity active, distance: " + distance);
-                }
-                goToSleepLocked(milliseconds);
-                mProximitySensorActive = true;
+    private void enableLightSensor(boolean enable) {
+        if (mDebugLightSensor) {
+            Log.d(TAG, "enableLightSensor " + enable);
+        }
+        if (mSensorManager != null && mLightSensorEnabled != enable) {
+            mLightSensorEnabled = enable;
+            if (enable) {
+                mSensorManager.registerListener(mLightListener, mLightSensor,
+                        SensorManager.SENSOR_DELAY_NORMAL);
             } else {
-                // proximity sensor negative events trigger as user activity.
-                // temporarily set mUserActivityAllowed to true so this will work
-                // even when the keyguard is on.
-                if (mSpew) {
-                    Log.d(TAG, "onSensorChanged: proximity inactive, distance: " + distance);
-                }
-                mProximitySensorActive = false;
-                forceUserActivityLocked();
+                mSensorManager.unregisterListener(mLightListener);
+                mHandler.removeCallbacks(mAutoBrightnessTask);
             }
         }
     }
 
-    public void onAccuracyChanged(Sensor sensor, int accuracy) {
-        // ignore
-    }
+    SensorEventListener mProximityListener = new SensorEventListener() {
+        public void onSensorChanged(SensorEvent event) {
+            long milliseconds = event.timestamp / 1000000;
+            synchronized (mLocks) {
+                float distance = event.values[0];
+                // compare against getMaximumRange to support sensors that only return 0 or 1
+                if (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
+                        distance < mProximitySensor.getMaximumRange()) {
+                    if (mSpew) {
+                        Log.d(TAG, "onSensorChanged: proximity active, distance: " + distance);
+                    }
+                    goToSleepLocked(milliseconds);
+                    mProximitySensorActive = true;
+                } else {
+                    // proximity sensor negative events trigger as user activity.
+                    // temporarily set mUserActivityAllowed to true so this will work
+                    // even when the keyguard is on.
+                    if (mSpew) {
+                        Log.d(TAG, "onSensorChanged: proximity inactive, distance: " + distance);
+                    }
+                    mProximitySensorActive = false;
+                    forceUserActivityLocked();
+                }
+            }
+        }
+
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+            // ignore
+        }
+    };
+
+    SensorEventListener mLightListener = new SensorEventListener() {
+        public void onSensorChanged(SensorEvent event) {
+            synchronized (mLocks) {
+                int value = (int)event.values[0];
+                if (mDebugLightSensor) {
+                    Log.d(TAG, "onSensorChanged: light value: " + value);
+                }
+                mHandler.removeCallbacks(mAutoBrightnessTask);
+                if (mLightSensorValue != value) {
+                    if (mLightSensorValue == -1) {
+                        // process the value immediately
+                        lightSensorChangedLocked(value);
+                    } else {
+                        // delay processing to debounce the sensor
+                        mLightSensorPendingValue = value;
+                        mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
+                    }
+                } else {
+                    mLightSensorPendingValue = -1;
+                }
+            }
+        }
+
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+            // ignore
+        }
+    };
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index b8cf844..1a7416a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -43,6 +43,7 @@
 import android.util.Log;
 import android.accounts.AccountManagerService;
 
+import java.io.File;
 import java.util.Timer;
 import java.util.TimerTask;
 
@@ -294,6 +295,14 @@
             }
 
             try {
+                Log.i(TAG, "DropBox Service");
+                ServiceManager.addService("dropbox",
+                        new DropBoxService(context, new File("/data/system/dropbox")));
+            } catch (Throwable e) {
+                Log.e(TAG, "Failure starting DropBox Service", e);
+            }
+
+            try {
                 Log.i(TAG, "Checkin Service");
                 Intent intent = new Intent().setComponent(new ComponentName(
                         "com.google.android.server.checkin",
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 101b075..47cb6ad 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -477,7 +477,7 @@
     private void broadcastServiceStateChanged(ServiceState state) {
         long ident = Binder.clearCallingIdentity();
         try {
-            mBatteryStats.noteAirplaneMode(state.getState() == ServiceState.STATE_POWER_OFF);
+            mBatteryStats.notePhoneState(state.getState());
         } catch (RemoteException re) {
             // Can't do much
         } finally {
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 61537f5..5a1619a 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -51,6 +51,9 @@
         mContext = context;
         ServiceManager.addService("batteryinfo", asBinder());
         mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps());
+        mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_radioScanningTimeout)
+                * 1000L);
     }
     
     public void shutdown() {
@@ -195,10 +198,10 @@
         }
     }
 
-    public void noteAirplaneMode(boolean airplaneMode) {
+    public void notePhoneState(int state) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteAirplaneModeLocked(airplaneMode);
+            mStats.notePhoneStateLocked(state);
         }
     }
 
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index fe761ea..59e9832 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -140,7 +140,7 @@
             boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
             switch (event.getKeyCode()) {
             case KeyEvent.KEYCODE_BACK:
-                if (down) {
+                if (!down) {
                     StatusBarService.this.deactivate();
                 }
                 return true;
@@ -973,15 +973,24 @@
     }
     
     void animateCollapse() {
-        if (SPEW) Log.d(TAG, "Animate collapse: expanded=" + mExpanded
-                + " expanded visible=" + mExpandedVisible);
+        if (SPEW) {
+            Log.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
+                    + " mExpandedVisible=" + mExpandedVisible
+                    + " mAnimating=" + mAnimating
+                    + " mAnimVel=" + mAnimVel);
+        }
         
         if (!mExpandedVisible) {
             return;
         }
 
-        prepareTracking(mDisplay.getHeight()-1);
-        performFling(mDisplay.getHeight()-1, -2000.0f, true);
+        if (mAnimating) {
+            return;
+        }
+
+        int y = mDisplay.getHeight()-1;
+        prepareTracking(y);
+        performFling(y, -2000.0f, true);
     }
     
     void performExpand() {
@@ -1096,7 +1105,7 @@
         mTracking = true;
         mVelocityTracker = VelocityTracker.obtain();
         boolean opening = !mExpanded;
-        if (!mExpanded) {
+        if (opening) {
             mAnimAccel = 2000.0f;
             mAnimVel = 200;
             mAnimY = mStatusBarView.getHeight();
@@ -1111,16 +1120,13 @@
             mAnimating = true;
             mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE_REVEAL),
                     mCurAnimationTime);
+            makeExpandedVisible();
         } else {
             // it's open, close it?
             if (mAnimating) {
                 mAnimating = false;
                 mHandler.removeMessages(MSG_ANIMATE);
             }
-        }
-        if (opening) {
-            makeExpandedVisible();
-        } else {
             updateExpandedViewPos(y + mViewDelta);
         }
     }
@@ -1547,7 +1553,7 @@
 
     void updateExpandedViewPos(int expandedPosition) {
         if (SPEW) {
-            Log.d(TAG, "updateExpandedViewPos before pos=" + expandedPosition
+            Log.d(TAG, "updateExpandedViewPos before expandedPosition=" + expandedPosition
                     + " mTrackingParams.y=" + mTrackingParams.y
                     + " mTrackingPosition=" + mTrackingPosition);
         }
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index d26a092..53c0bef 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -303,6 +303,7 @@
                     notifyAndAcknowledgeLastIncomingSms(handled, result, null);
                 }
             } catch (RuntimeException ex) {
+                Log.e(TAG, "Exception dispatching message", ex);
                 notifyAndAcknowledgeLastIncomingSms(false, Intents.RESULT_SMS_GENERIC_ERROR, null);
             }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 7baf770..d895cd4 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -100,6 +100,7 @@
 
         // If sms is null, means there was a parsing error.
         if (smsb == null) {
+            Log.e(TAG, "dispatchMessage: message is null");
             return Intents.RESULT_SMS_GENERIC_ERROR;
         }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriManager.java b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
index 9b23cdf..083fa0b 100644
--- a/telephony/java/com/android/internal/telephony/cdma/EriManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
@@ -288,7 +288,7 @@
         if (isEriFileLoaded) {
             EriInfo eriInfo = getEriInfo(roamInd);
             if (eriInfo != null) {
-                if (DBG) Log.d(LOG_TAG, "ERI roamInd " + roamInd + " found in ERI file");
+                if (VDBG) Log.v(LOG_TAG, "ERI roamInd " + roamInd + " found in ERI file");
                 ret = new EriDisplayInformation(
                         eriInfo.mIconIndex,
                         eriInfo.mIconMode,
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index 18e6375..bcbd127 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -595,7 +595,8 @@
                     }
 
                     int isSettingUnconditionalVoice =
-                        ((reason == CommandsInterface.CF_REASON_UNCONDITIONAL) &&
+                        (((reason == CommandsInterface.CF_REASON_UNCONDITIONAL) ||
+                                (reason == CommandsInterface.CF_REASON_ALL)) &&
                                 (((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) ||
                                  (serviceClass == CommandsInterface.SERVICE_CLASS_NONE))) ? 1 : 0;
 
diff --git a/tests/AndroidTests/Android.mk b/tests/AndroidTests/Android.mk
index ced796a..757044f 100644
--- a/tests/AndroidTests/Android.mk
+++ b/tests/AndroidTests/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := framework-tests android.test.runner
+LOCAL_JAVA_LIBRARIES := framework-tests android.test.runner services
 
 LOCAL_STATIC_JAVA_LIBRARIES := googlelogin-client
 
diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml
index d94327a..786178c 100644
--- a/tests/AndroidTests/AndroidManifest.xml
+++ b/tests/AndroidTests/AndroidManifest.xml
@@ -35,27 +35,27 @@
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
-    <uses-permission android:name="android.permission.READ_CONTACTS" />
-    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
-    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
-    <uses-permission android:name="android.permission.READ_SMS"/>
-    <uses-permission android:name="android.permission.WRITE_SMS"/>
-    <uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
     <uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
     <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
+    <uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
     <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
-    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.WRITE_GSERVICES" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
-    <uses-permission android:name="com.android.unit_tests.permission.TEST_GRANTED" />
-
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.READ_LOGS"/>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.READ_SMS"/>
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_GSERVICES" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SMS"/>
+    <uses-permission android:name="com.android.unit_tests.permission.TEST_GRANTED" />
+    <uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" />
     <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" />
+
     <!-- InstrumentationTestRunner for AndroidTests -->
     <instrumentation android:name="android.test.InstrumentationTestRunner"
                      android:targetPackage="com.android.unit_tests"
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DropBoxTest.java b/tests/AndroidTests/src/com/android/unit_tests/DropBoxTest.java
new file mode 100644
index 0000000..77ebf8d
--- /dev/null
+++ b/tests/AndroidTests/src/com/android/unit_tests/DropBoxTest.java
@@ -0,0 +1,479 @@
+/*
+ * 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.unit_tests;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.DropBoxEntry;
+import android.os.IDropBox;
+import android.os.ParcelFileDescriptor;
+import android.os.ServiceManager;
+import android.os.StatFs;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+
+import com.android.server.DropBoxService;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.util.Random;
+import java.util.zip.GZIPOutputStream;
+
+/** Test {@link IDropBox} functionality. */
+public class DropBoxTest extends AndroidTestCase {
+    public void tearDown() throws Exception {
+        Intent override = new Intent(Settings.Gservices.OVERRIDE_ACTION);
+        override.putExtra(Settings.Gservices.DROPBOX_AGE_SECONDS, "");
+        override.putExtra(Settings.Gservices.DROPBOX_QUOTA_KB, "");
+        override.putExtra(Settings.Gservices.DROPBOX_TAG_PREFIX + "DropBoxTest", "");
+        waitForBroadcast(override);
+    }
+
+    public void testAddText() throws Exception {
+        IDropBox dropbox = IDropBox.Stub.asInterface(ServiceManager.getService("dropbox"));
+        long before = System.currentTimeMillis();
+        Thread.sleep(5);
+        dropbox.addText("DropBoxTest", "TEST0");
+        Thread.sleep(5);
+        long between = System.currentTimeMillis();
+        Thread.sleep(5);
+        dropbox.addText("DropBoxTest", "TEST1");
+        dropbox.addText("DropBoxTest", "TEST2");
+        Thread.sleep(5);
+        long after = System.currentTimeMillis();
+
+        DropBoxEntry e0 = getNextTestEntry(dropbox, before);
+        DropBoxEntry e1 = getNextTestEntry(dropbox, e0.getTimeMillis());
+        DropBoxEntry e2 = getNextTestEntry(dropbox, e1.getTimeMillis());
+        assertTrue(null == getNextTestEntry(dropbox, e2.getTimeMillis()));
+
+        assertTrue(e0.getTimeMillis() > before);
+        assertTrue(e0.getTimeMillis() < between);
+        assertTrue(e1.getTimeMillis() > between);
+        assertTrue(e1.getTimeMillis() < e2.getTimeMillis());
+        assertTrue(e2.getTimeMillis() < after);
+
+        assertEquals("TEST0", e0.getText(80));
+        assertEquals("TEST1", e1.getText(80));
+        assertEquals("TES", e2.getText(3));
+
+        e0.close();
+        e1.close();
+        e2.close();
+    }
+
+    public void testAddData() throws Exception {
+        IDropBox dropbox = IDropBox.Stub.asInterface(ServiceManager.getService("dropbox"));
+        long before = System.currentTimeMillis();
+        dropbox.addData("DropBoxTest", "TEST".getBytes(), 0);
+        long after = System.currentTimeMillis();
+
+        DropBoxEntry e = getNextTestEntry(dropbox, before);
+        assertTrue(null == getNextTestEntry(dropbox, e.getTimeMillis()));
+
+        assertEquals("DropBoxTest", e.getTag());
+        assertTrue(e.getTimeMillis() >= before);
+        assertEquals(0, e.getFlags());
+        assertTrue(null == e.getText(80));
+
+        byte[] buf = new byte[80];
+        assertEquals("TEST", new String(buf, 0, e.getInputStream().read(buf)));
+
+        e.close();
+    }
+
+    public void testAddFile() throws Exception {
+        File dir = getEmptyDir("testAddFile");
+        long before = System.currentTimeMillis();
+
+        File f0 = new File(dir, "f0.txt");
+        File f1 = new File(dir, "f1.txt.gz");
+        File f2 = new File(dir, "f2.dat");
+        File f3 = new File(dir, "f2.dat.gz");
+
+        FileWriter w0 = new FileWriter(f0);
+        GZIPOutputStream gz1 = new GZIPOutputStream(new FileOutputStream(f1));
+        FileOutputStream os2 = new FileOutputStream(f2);
+        GZIPOutputStream gz3 = new GZIPOutputStream(new FileOutputStream(f3));
+
+        w0.write("FILE0");
+        gz1.write("FILE1".getBytes());
+        os2.write("DATA2".getBytes());
+        gz3.write("DATA3".getBytes());
+
+        w0.close();
+        gz1.close();
+        os2.close();
+        gz3.close();
+
+        IDropBox dropbox = IDropBox.Stub.asInterface(ServiceManager.getService("dropbox"));
+        int mode = ParcelFileDescriptor.MODE_READ_ONLY;
+
+        ParcelFileDescriptor pfd0 = ParcelFileDescriptor.open(f0, mode);
+        ParcelFileDescriptor pfd1 = ParcelFileDescriptor.open(f1, mode);
+        ParcelFileDescriptor pfd2 = ParcelFileDescriptor.open(f2, mode);
+        ParcelFileDescriptor pfd3 = ParcelFileDescriptor.open(f3, mode);
+
+        dropbox.addFile("DropBoxTest", pfd0, DropBoxEntry.IS_TEXT);
+        dropbox.addFile("DropBoxTest", pfd1, DropBoxEntry.IS_TEXT | DropBoxEntry.IS_GZIPPED);
+        dropbox.addFile("DropBoxTest", pfd2, 0);
+        dropbox.addFile("DropBoxTest", pfd3, DropBoxEntry.IS_GZIPPED);
+
+        pfd0.close();
+        pfd1.close();
+        pfd2.close();
+        pfd3.close();
+
+        DropBoxEntry e0 = getNextTestEntry(dropbox, before);
+        DropBoxEntry e1 = getNextTestEntry(dropbox, e0.getTimeMillis());
+        DropBoxEntry e2 = getNextTestEntry(dropbox, e1.getTimeMillis());
+        DropBoxEntry e3 = getNextTestEntry(dropbox, e2.getTimeMillis());
+        assertTrue(null == getNextTestEntry(dropbox, e3.getTimeMillis()));
+
+        assertTrue(e0.getTimeMillis() > before);
+        assertTrue(e1.getTimeMillis() > e0.getTimeMillis());
+        assertTrue(e2.getTimeMillis() > e1.getTimeMillis());
+        assertTrue(e3.getTimeMillis() > e2.getTimeMillis());
+
+        assertEquals(DropBoxEntry.IS_TEXT, e0.getFlags());
+        assertEquals(DropBoxEntry.IS_TEXT, e1.getFlags());
+        assertEquals(0, e2.getFlags());
+        assertEquals(0, e3.getFlags());
+
+        assertEquals("FILE0", e0.getText(80));
+
+        byte[] buf1 = new byte[80];
+        assertEquals("FILE1", new String(buf1, 0, e1.getInputStream().read(buf1)));
+
+        assertTrue(null == e2.getText(80));
+        byte[] buf2 = new byte[80];
+        assertEquals("DATA2", new String(buf2, 0, e2.getInputStream().read(buf2)));
+
+        assertTrue(null == e3.getText(80));
+        byte[] buf3 = new byte[80];
+        assertEquals("DATA3", new String(buf3, 0, e3.getInputStream().read(buf3)));
+
+        e0.close();
+        e1.close();
+        e2.close();
+        e3.close();
+    }
+
+    public void testAddEntriesInTheFuture() throws Exception {
+        File dir = getEmptyDir("testAddEntriesInTheFuture");
+        long before = System.currentTimeMillis();
+
+        // Near future: should be allowed to persist
+        FileWriter w0 = new FileWriter(new File(dir, "DropBoxTest@" + (before + 5000) + ".txt"));
+        w0.write("FUTURE0");
+        w0.close();
+
+        // Far future: should be collapsed
+        FileWriter w1 = new FileWriter(new File(dir, "DropBoxTest@" + (before + 100000) + ".txt"));
+        w1.write("FUTURE1");
+        w1.close();
+
+        // Another far future item, this one gzipped
+        File f2 = new File(dir, "DropBoxTest@" + (before + 100001) + ".txt.gz");
+        GZIPOutputStream gz2 = new GZIPOutputStream(new FileOutputStream(f2));
+        gz2.write("FUTURE2".getBytes());
+        gz2.close();
+
+        // Tombstone in the far future
+        new FileOutputStream(new File(dir, "DropBoxTest@" + (before + 100002) + ".lost")).close();
+
+        DropBoxService dropbox = new DropBoxService(getContext(), dir);
+
+        // Until a write, the timestamps are taken at face value
+        DropBoxEntry e0 = getNextTestEntry(dropbox, before);
+        DropBoxEntry e1 = getNextTestEntry(dropbox, e0.getTimeMillis());
+        DropBoxEntry e2 = getNextTestEntry(dropbox, e1.getTimeMillis());
+        DropBoxEntry e3 = getNextTestEntry(dropbox, e2.getTimeMillis());
+        assertTrue(null == getNextTestEntry(dropbox, e3.getTimeMillis()));
+
+        assertEquals("FUTURE0", e0.getText(80));
+        assertEquals("FUTURE1", e1.getText(80));
+        assertEquals("FUTURE2", e2.getText(80));
+        assertEquals(null, e3.getText(80));
+
+        assertEquals(before + 5000, e0.getTimeMillis());
+        assertEquals(before + 100000, e1.getTimeMillis());
+        assertEquals(before + 100001, e2.getTimeMillis());
+        assertEquals(before + 100002, e3.getTimeMillis());
+
+        e0.close();
+        e1.close();
+        e2.close();
+        e3.close();
+
+        // Write something to force a collapse
+        dropbox.addText("NotDropBoxTest", "FUTURE");
+        e0 = getNextTestEntry(dropbox, before);
+        e1 = getNextTestEntry(dropbox, e0.getTimeMillis());
+        e2 = getNextTestEntry(dropbox, e1.getTimeMillis());
+        e3 = getNextTestEntry(dropbox, e2.getTimeMillis());
+        assertTrue(null == getNextTestEntry(dropbox, e3.getTimeMillis()));
+
+        assertEquals("FUTURE0", e0.getText(80));
+        assertEquals("FUTURE1", e1.getText(80));
+        assertEquals("FUTURE2", e2.getText(80));
+        assertEquals(null, e3.getText(80));
+
+        assertEquals(before + 5000, e0.getTimeMillis());
+        assertEquals(before + 5001, e1.getTimeMillis());
+        assertEquals(before + 5002, e2.getTimeMillis());
+        assertEquals(before + 5003, e3.getTimeMillis());
+
+        e0.close();
+        e1.close();
+        e2.close();
+        e3.close();
+        dropbox.stop();
+    }
+
+    public void testIsTagEnabled() throws Exception {
+        IDropBox dropbox = IDropBox.Stub.asInterface(ServiceManager.getService("dropbox"));
+        long before = System.currentTimeMillis();
+        dropbox.addText("DropBoxTest", "TEST-ENABLED");
+        assertTrue(dropbox.isTagEnabled("DropBoxTest"));
+
+        Intent override = new Intent(Settings.Gservices.OVERRIDE_ACTION);
+        override.putExtra(Settings.Gservices.DROPBOX_TAG_PREFIX + "DropBoxTest", "disabled");
+        waitForBroadcast(override);
+
+        dropbox.addText("DropBoxTest", "TEST-DISABLED");
+        assertFalse(dropbox.isTagEnabled("DropBoxTest"));
+
+        override = new Intent(Settings.Gservices.OVERRIDE_ACTION);
+        override.putExtra(Settings.Gservices.DROPBOX_TAG_PREFIX + "DropBoxTest", "");
+        waitForBroadcast(override);
+
+        dropbox.addText("DropBoxTest", "TEST-ENABLED-AGAIN");
+        assertTrue(dropbox.isTagEnabled("DropBoxTest"));
+
+        DropBoxEntry e0 = getNextTestEntry(dropbox, before);
+        DropBoxEntry e1 = getNextTestEntry(dropbox, e0.getTimeMillis());
+        assertTrue(null == getNextTestEntry(dropbox, e1.getTimeMillis()));
+
+        assertEquals("TEST-ENABLED", e0.getText(80));
+        assertEquals("TEST-ENABLED-AGAIN", e1.getText(80));
+
+        e0.close();
+        e1.close();
+    }
+
+    public void testSizeLimits() throws Exception {
+        File dir = getEmptyDir("testSizeLimits");
+        int blockSize =  new StatFs(dir.getPath()).getBlockSize();
+
+        // Limit storage to 10 blocks
+        int kb = blockSize * 10 / 1024;
+        Intent override = new Intent(Settings.Gservices.OVERRIDE_ACTION);
+        override.putExtra(Settings.Gservices.DROPBOX_QUOTA_KB, Integer.toString(kb));
+        waitForBroadcast(override);
+
+        // Three tags using a total of 12 blocks:
+        // DropBoxTest0 [ ][ ]
+        // DropBoxTest1 [x][ ][    ][ ][xxx(20 blocks)xxx]
+        // DropBoxTest2 [xxxxxxxxxx][ ][ ]
+        //
+        // The blocks marked "x" will be removed due to storage restrictions.
+        // Use random fill (so it doesn't compress), subtract a little for gzip overhead
+
+        final int overhead = 64;
+        long before = System.currentTimeMillis();
+        DropBoxService dropbox = new DropBoxService(getContext(), dir);
+        addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead);
+        addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead);
+
+        addRandomEntry(dropbox, "DropBoxTest1", blockSize - overhead);
+        addRandomEntry(dropbox, "DropBoxTest1", blockSize - overhead);
+        addRandomEntry(dropbox, "DropBoxTest1", blockSize * 2 - overhead);
+        addRandomEntry(dropbox, "DropBoxTest1", blockSize - overhead);
+        addRandomEntry(dropbox, "DropBoxTest1", blockSize * 20 - overhead);
+
+        addRandomEntry(dropbox, "DropBoxTest2", blockSize * 4 - overhead);
+        addRandomEntry(dropbox, "DropBoxTest2", blockSize - overhead);
+        addRandomEntry(dropbox, "DropBoxTest2", blockSize - overhead);
+
+        DropBoxEntry e0 = getNextTestEntry(dropbox, before);
+        DropBoxEntry e1 = getNextTestEntry(dropbox, e0.getTimeMillis());
+        DropBoxEntry e2 = getNextTestEntry(dropbox, e1.getTimeMillis());
+        DropBoxEntry e3 = getNextTestEntry(dropbox, e2.getTimeMillis());
+        DropBoxEntry e4 = getNextTestEntry(dropbox, e3.getTimeMillis());
+        DropBoxEntry e5 = getNextTestEntry(dropbox, e4.getTimeMillis());
+        DropBoxEntry e6 = getNextTestEntry(dropbox, e5.getTimeMillis());
+        DropBoxEntry e7 = getNextTestEntry(dropbox, e6.getTimeMillis());
+        DropBoxEntry e8 = getNextTestEntry(dropbox, e7.getTimeMillis());
+        DropBoxEntry e9 = getNextTestEntry(dropbox, e8.getTimeMillis());
+        assertTrue(null == getNextTestEntry(dropbox, e9.getTimeMillis()));
+
+        assertEquals("DropBoxTest0", e0.getTag());
+        assertEquals("DropBoxTest0", e1.getTag());
+        assertEquals(blockSize - overhead, getEntrySize(e0));
+        assertEquals(blockSize - overhead, getEntrySize(e1));
+
+        assertEquals("DropBoxTest1", e2.getTag());
+        assertEquals("DropBoxTest1", e3.getTag());
+        assertEquals("DropBoxTest1", e4.getTag());
+        assertEquals("DropBoxTest1", e5.getTag());
+        assertEquals("DropBoxTest1", e6.getTag());
+        assertEquals(-1, getEntrySize(e2));  // Tombstone
+        assertEquals(blockSize - overhead, getEntrySize(e3));
+        assertEquals(blockSize * 2 - overhead, getEntrySize(e4));
+        assertEquals(blockSize - overhead, getEntrySize(e5));
+        assertEquals(-1, getEntrySize(e6));
+
+        assertEquals("DropBoxTest2", e7.getTag());
+        assertEquals("DropBoxTest2", e8.getTag());
+        assertEquals("DropBoxTest2", e9.getTag());
+        assertEquals(-1, getEntrySize(e7));  // Tombstone
+        assertEquals(blockSize - overhead, getEntrySize(e8));
+        assertEquals(blockSize - overhead, getEntrySize(e9));
+
+        e0.close();
+        e1.close();
+        e2.close();
+        e3.close();
+        e4.close();
+        e5.close();
+        e6.close();
+        e7.close();
+        e8.close();
+        e9.close();
+        dropbox.stop();
+    }
+
+    public void testAgeLimits() throws Exception {
+        File dir = getEmptyDir("testAgeLimits");
+        int blockSize = new StatFs(dir.getPath()).getBlockSize();
+
+        // Limit storage to 10 blocks with an expiration of 1 second
+        int kb = blockSize * 10 / 1024;
+        Intent override = new Intent(Settings.Gservices.OVERRIDE_ACTION);
+        override.putExtra(Settings.Gservices.DROPBOX_AGE_SECONDS, "1");
+        override.putExtra(Settings.Gservices.DROPBOX_QUOTA_KB, Integer.toString(kb));
+        waitForBroadcast(override);
+
+        // Write one normal entry and another so big that it is instantly tombstoned
+        long before = System.currentTimeMillis();
+        DropBoxService dropbox = new DropBoxService(getContext(), dir);
+        dropbox.addText("DropBoxTest", "TEST");
+        addRandomEntry(dropbox, "DropBoxTest", blockSize * 20);
+
+        // Verify that things are as expected
+        DropBoxEntry e0 = getNextTestEntry(dropbox, before);
+        DropBoxEntry e1 = getNextTestEntry(dropbox, e0.getTimeMillis());
+        assertTrue(null == getNextTestEntry(dropbox, e1.getTimeMillis()));
+
+        assertEquals("TEST", e0.getText(80));
+        assertEquals(null, e1.getText(80));
+        assertEquals(-1, getEntrySize(e1));
+
+        e0.close();
+        e1.close();
+
+        // Wait a second and write another entry -- old ones should be expunged
+        Thread.sleep(2000);
+        dropbox.addText("DropBoxTest", "TEST1");
+
+        e0 = getNextTestEntry(dropbox, before);
+        assertTrue(null == getNextTestEntry(dropbox, e0.getTimeMillis()));
+        assertEquals("TEST1", e0.getText(80));
+        e0.close();
+    }
+
+    public void testCreateDropBoxWithInvalidDirectory() throws Exception {
+        // If created with an invalid directory, the DropBox should suffer quietly
+        // and fail all operations (this is how it survives a full disk).
+        // Once the directory becomes possible to create, it will start working.
+
+        File dir = new File(getEmptyDir("testCreateDropBoxWith"), "InvalidDirectory");
+        new FileOutputStream(dir).close();  // Create an empty file
+        DropBoxService dropbox = new DropBoxService(getContext(), dir);
+
+        dropbox.addText("DropBoxTest", "should be ignored");
+        dropbox.addData("DropBoxTest", "should be ignored".getBytes(), 0);
+        assertTrue(null == getNextTestEntry(dropbox, 0));
+
+        dir.delete();  // Remove the file so a directory can be created
+        dropbox.addText("DropBoxTest", "TEST");
+        DropBoxEntry e = getNextTestEntry(dropbox, 0);
+        assertTrue(null == getNextTestEntry(dropbox, e.getTimeMillis()));
+        assertEquals("DropBoxTest", e.getTag());
+        assertEquals("TEST", e.getText(80));
+        e.close();
+        dropbox.stop();
+    }
+
+    private void addRandomEntry(IDropBox dropbox, String tag, int size) throws Exception {
+        byte[] bytes = new byte[size];
+        new Random(System.currentTimeMillis()).nextBytes(bytes);
+
+        File f = new File(getEmptyDir("addRandomEntry"), "random.dat");
+        FileOutputStream os = new FileOutputStream(f);
+        os.write(bytes);
+        os.close();
+
+        ParcelFileDescriptor fd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
+        dropbox.addFile(tag, fd, 0);
+        fd.close();
+    }
+
+    private int getEntrySize(DropBoxEntry e) throws Exception {
+        InputStream is = e.getInputStream();
+        if (is == null) return -1;
+        int length = 0;
+        while (is.read() != -1) length++;
+        return length;
+    }
+
+    private void waitForBroadcast(Intent intent) throws InterruptedException {
+        BroadcastReceiver receiver = new BroadcastReceiver() {
+            public synchronized void onReceive(Context context, Intent intent) { notify(); }
+        };
+
+        getContext().sendOrderedBroadcast(intent, null, receiver, null, 0, null, null);
+        synchronized (receiver) { receiver.wait(); }
+    }
+
+    private void recursiveDelete(File file) {
+        if (!file.delete() && file.isDirectory()) {
+            for (File f : file.listFiles()) recursiveDelete(f);
+            file.delete();
+        }
+    }
+
+    private File getEmptyDir(String name) {
+        File dir = getContext().getDir("DropBoxTest." + name, 0);
+        for (File f : dir.listFiles()) recursiveDelete(f);
+        assertTrue(dir.listFiles().length == 0);
+        return dir;
+    }
+
+    private DropBoxEntry getNextTestEntry(IDropBox dropbox, long millis) throws Exception {
+        for (;;) {
+            DropBoxEntry entry = dropbox.getNextEntry(millis);
+            if (entry == null || entry.getTag().startsWith("DropBoxTest")) return entry;
+            entry.close();
+            millis = entry.getTimeMillis();
+        }
+    }
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java
index 3acd6c1..b009e2d 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java
@@ -230,6 +230,6 @@
         }
         mTestCase.fail("Property \"" + propName + "\" has wrong value.\n"
                 + builder.toString()
-                + " actual: " + actualNode.toString());
+                + "  actual: " + actualNode.toString());
     }
 }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java
index 3f10605..976474f 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java
@@ -44,8 +44,17 @@
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Event;
+import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.CommonDataKinds.Nickname;
+import android.provider.ContactsContract.CommonDataKinds.Note;
+import android.provider.ContactsContract.CommonDataKinds.Organization;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
+import android.provider.ContactsContract.CommonDataKinds.Website;
 import android.test.AndroidTestCase;
 import android.test.mock.MockContentResolver;
 import android.test.mock.MockContext;
@@ -147,7 +156,10 @@
  * the result of this class will not be reliable.
  */
 public class VCardExporterTests extends AndroidTestCase {
-    /* package */ static final byte[] sPhotoByteArray =
+    private static final int V21 = 0;
+    private static final int V30 = 1;
+
+    private static final byte[] sPhotoByteArray =
         VCardImporterTests.sPhotoByteArrayForComplicatedCase;
 
     public class ExportTestResolver extends MockContentResolver {
@@ -282,17 +294,26 @@
         final private boolean mIsV30;
         int mCount;
 
-        public VCardVerificationHandler(TestCase testCase, boolean isV30) {
+        public VCardVerificationHandler(TestCase testCase, int version) {
             mTestCase = testCase;
             mPropertyNodesVerifierList = new ArrayList<PropertyNodesVerifier>();
-            mIsV30 = isV30;
+            mIsV30 = (version == V30);
             mCount = 1;
         }
 
-        public PropertyNodesVerifier addNewPropertyNodesVerifier() {
-            PropertyNodesVerifier propertyNodesVerifier = new PropertyNodesVerifier(mTestCase);
-            mPropertyNodesVerifierList.add(propertyNodesVerifier);
-            return propertyNodesVerifier;
+        public PropertyNodesVerifier addNewVerifier() {
+            PropertyNodesVerifier verifier = new PropertyNodesVerifier(mTestCase);
+            mPropertyNodesVerifierList.add(verifier);
+            verifier.addNodeWithOrder("VERSION", mIsV30 ? "3.0" : "2.1");
+            return verifier;
+        }
+
+        public PropertyNodesVerifier addNewVerifierWithEmptyName() {
+            PropertyNodesVerifier verifier = addNewVerifier();
+            if (mIsV30) {
+                verifier.addNodeWithOrder("N", "").addNodeWithOrder("FN", "");
+            }
+            return verifier;
         }
 
         public boolean onInit(Context context) {
@@ -344,50 +365,12 @@
 
     //// Followings are actual tests ////
 
-    public void testSimple() {
-        ExportTestResolver resolver = new ExportTestResolver();
-        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "Ando");
-        contentValues.put(StructuredName.GIVEN_NAME, "Roid");
+    private void verifyOneComposition(ExportTestResolver resolver,
+            VCardVerificationHandler handler, int version) {
+        final boolean isV30 = (version == V30);
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, false);
-        handler.addNewPropertyNodesVerifier()
-            .addNodeWithOrder("VERSION", "2.1")
-            .addNodeWithoutOrder("FN", "Roid Ando")
-            .addNodeWithoutOrder("N", "Ando;Roid;;;", Arrays.asList("Ando", "Roid", "", "", ""));
-
-        VCardComposer composer = new VCardComposer(new CustomMockContext(resolver),
-                VCardConfig.VCARD_TYPE_V21_GENERIC);
-        composer.addHandler(handler);
-        if (!composer.init(VCardComposer.CONTACTS_TEST_CONTENT_URI, null, null, null)) {
-            fail("init failed. Reason: " + composer.getErrorReason());
-        }
-        assertFalse(composer.isAfterLast());
-        assertTrue(composer.createOneEntry());
-        assertTrue(composer.isAfterLast());
-        composer.terminate();
-    }
-
-    private void testPhotoCommon(boolean isV30) {
-        ExportTestResolver resolver = new ExportTestResolver();
-        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "PhotoTest");
-
-        contentValues = resolver.buildData(Photo.CONTENT_ITEM_TYPE);
-        contentValues.put(Photo.PHOTO, sPhotoByteArray);
-
-        ContentValues contentValuesForPhoto = new ContentValues();
-        contentValuesForPhoto.put("ENCODING", (isV30 ? "b" : "BASE64"));
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, isV30);
-        handler.addNewPropertyNodesVerifier()
-            .addNodeWithOrder("VERSION", (isV30 ? "3.0" : "2.1"))
-            .addNodeWithoutOrder("FN", "PhotoTest")
-            .addNodeWithoutOrder("N", "PhotoTest;;;;", Arrays.asList("PhotoTest", "", "", "", ""))
-            .addNodeWithOrder("PHOTO", null, null, sPhotoByteArray,
-                    contentValuesForPhoto, new TypeSet("JPEG"), null);
-
-        int vcardType = (isV30 ? VCardConfig.VCARD_TYPE_V30_GENERIC
-                : VCardConfig.VCARD_TYPE_V21_GENERIC);
+        int vcardType = (isV30 ? VCardConfig.VCARD_TYPE_V30_GENERIC_UTF8
+                : VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         VCardComposer composer = new VCardComposer(new CustomMockContext(resolver), vcardType);
         composer.addHandler(handler);
         if (!composer.init(VCardComposer.CONTACTS_TEST_CONTENT_URI, null, null, null)) {
@@ -399,11 +382,830 @@
         composer.terminate();
     }
 
+    public void testSimpleV21() {
+        ExportTestResolver resolver = new ExportTestResolver();
+        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredName.FAMILY_NAME, "Ando");
+        contentValues.put(StructuredName.GIVEN_NAME, "Roid");
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, V21);
+        handler.addNewVerifier()
+            .addNodeWithoutOrder("FN", "Roid Ando")
+            .addNodeWithoutOrder("N", "Ando;Roid;;;", Arrays.asList("Ando", "Roid", "", "", ""));
+
+        verifyOneComposition(resolver, handler, V21);
+    }
+
+    private void testStructuredNameBasic(int version) {
+        final boolean isV30 = (version == V30);
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredName.FAMILY_NAME, "AppropriateFamilyName");
+        contentValues.put(StructuredName.GIVEN_NAME, "AppropriateGivenName");
+        contentValues.put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName");
+        contentValues.put(StructuredName.PREFIX, "AppropriatePrefix");
+        contentValues.put(StructuredName.SUFFIX, "AppropriateSuffix");
+        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily");
+        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven");
+        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle");
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        PropertyNodesVerifier verifier = handler.addNewVerifier()
+            .addNodeWithOrder("N",
+                    "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
+                    + "AppropriatePrefix;AppropriateSuffix",
+                    Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
+                            "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
+            .addNodeWithOrder("FN",
+                    "AppropriatePrefix AppropriateGivenName "
+                    + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
+            .addNodeWithoutOrder("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
+            .addNodeWithoutOrder("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
+            .addNodeWithoutOrder("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
+
+        if (isV30) {
+            verifier.addNodeWithoutOrder("SORT-STRING",
+                    "AppropriatePhoneticGiven AppropriatePhoneticMiddle "
+                    + "AppropriatePhoneticFamily");
+        }
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testStructuredNameBasicV21() {
+        testStructuredNameBasic(V21);
+    }
+
+    public void testStructuredNameBasicV30() {
+        testStructuredNameBasic(V30);
+    }
+
+    /**
+     * Test that only "primary" StructuredName is emitted, so that our vCard file
+     * will not confuse the external importer, assuming there may be some importer
+     * which presume that there's only one property toward each of  "N", "FN", etc.
+     * Note that more than one "N", "FN", etc. properties are acceptable in vCard spec.
+     */
+    private void testStructuredNameUsePrimaryCommon(int version) {
+        final boolean isV30 = (version == V30);
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1");
+        contentValues.put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1");
+        contentValues.put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1");
+        contentValues.put(StructuredName.PREFIX, "DoNotEmitPrefix1");
+        contentValues.put(StructuredName.SUFFIX, "DoNotEmitSuffix1");
+        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1");
+        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1");
+        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1");
+
+        // With "IS_PRIMARY=1". This is what we should use.
+        contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredName.FAMILY_NAME, "AppropriateFamilyName");
+        contentValues.put(StructuredName.GIVEN_NAME, "AppropriateGivenName");
+        contentValues.put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName");
+        contentValues.put(StructuredName.PREFIX, "AppropriatePrefix");
+        contentValues.put(StructuredName.SUFFIX, "AppropriateSuffix");
+        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily");
+        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven");
+        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle");
+        contentValues.put(StructuredName.IS_PRIMARY, 1);
+
+        // With "IS_PRIMARY=1", but we should ignore this time, since this is second, not first.
+        contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2");
+        contentValues.put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2");
+        contentValues.put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2");
+        contentValues.put(StructuredName.PREFIX, "DoNotEmitPrefix2");
+        contentValues.put(StructuredName.SUFFIX, "DoNotEmitSuffix2");
+        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2");
+        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2");
+        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2");
+        contentValues.put(StructuredName.IS_PRIMARY, 1);
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        PropertyNodesVerifier verifier = handler.addNewVerifier()
+            .addNodeWithOrder("N",
+                    "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
+                    + "AppropriatePrefix;AppropriateSuffix",
+                    Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
+                            "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
+            .addNodeWithOrder("FN",
+                    "AppropriatePrefix AppropriateGivenName "
+                    + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
+            .addNodeWithoutOrder("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
+            .addNodeWithoutOrder("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
+            .addNodeWithoutOrder("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
+
+        if (isV30) {
+            verifier.addNodeWithoutOrder("SORT-STRING",
+                    "AppropriatePhoneticGiven AppropriatePhoneticMiddle "
+                    + "AppropriatePhoneticFamily");
+        }
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testStructuredNameUsePrimaryV21() {
+        testStructuredNameUsePrimaryCommon(V21);
+    }
+
+    public void testStructuredNameUsePrimaryV30() {
+        testStructuredNameUsePrimaryCommon(V30);
+    }
+
+    /**
+     * Tests that only "super primary" StructuredName is emitted.
+     * See also the comment in {@link #testStructuredNameUsePrimaryCommon(int)}.
+     */
+    private void testStructuredNameUseSuperPrimaryCommon(int version) {
+        final boolean isV30 = (version == V30);
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1");
+        contentValues.put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1");
+        contentValues.put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1");
+        contentValues.put(StructuredName.PREFIX, "DoNotEmitPrefix1");
+        contentValues.put(StructuredName.SUFFIX, "DoNotEmitSuffix1");
+        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1");
+        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1");
+        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1");
+
+        // With "IS_PRIMARY=1", but we should ignore this time.
+        contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2");
+        contentValues.put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2");
+        contentValues.put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2");
+        contentValues.put(StructuredName.PREFIX, "DoNotEmitPrefix2");
+        contentValues.put(StructuredName.SUFFIX, "DoNotEmitSuffix2");
+        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2");
+        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2");
+        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2");
+        contentValues.put(StructuredName.IS_PRIMARY, 1);
+
+        // With "IS_SUPER_PRIMARY=1". This is what we should use.
+        contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredName.FAMILY_NAME, "AppropriateFamilyName");
+        contentValues.put(StructuredName.GIVEN_NAME, "AppropriateGivenName");
+        contentValues.put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName");
+        contentValues.put(StructuredName.PREFIX, "AppropriatePrefix");
+        contentValues.put(StructuredName.SUFFIX, "AppropriateSuffix");
+        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily");
+        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven");
+        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle");
+        contentValues.put(StructuredName.IS_SUPER_PRIMARY, 1);
+
+        contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName3");
+        contentValues.put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName3");
+        contentValues.put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName3");
+        contentValues.put(StructuredName.PREFIX, "DoNotEmitPrefix3");
+        contentValues.put(StructuredName.SUFFIX, "DoNotEmitSuffix3");
+        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily3");
+        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven3");
+        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle3");
+        contentValues.put(StructuredName.IS_PRIMARY, 1);
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        PropertyNodesVerifier verifier = handler.addNewVerifier()
+            .addNodeWithOrder("N",
+                    "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
+                    + "AppropriatePrefix;AppropriateSuffix",
+                    Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
+                            "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
+            .addNodeWithOrder("FN",
+                    "AppropriatePrefix AppropriateGivenName "
+                    + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
+            .addNodeWithoutOrder("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
+            .addNodeWithoutOrder("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
+            .addNodeWithoutOrder("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
+
+        if (isV30) {
+            verifier.addNodeWithoutOrder("SORT-STRING",
+                    "AppropriatePhoneticGiven AppropriatePhoneticMiddle"
+                    + " AppropriatePhoneticFamily");
+        }
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testStructuredNameUseSuperPrimaryV21() {
+        testStructuredNameUseSuperPrimaryCommon(V21);
+    }
+
+    public void testStructuredNameUseSuperPrimaryV30() {
+        testStructuredNameUseSuperPrimaryCommon(V30);
+    }
+
+    /**
+     * There's no property for nickname in vCard 2.1, so we don't have any requirement on it.
+     */
+    public void testNickNameV30() {
+        ExportTestResolver resolver = new ExportTestResolver();
+        ContentValues contentValues = resolver.buildData(Nickname.CONTENT_ITEM_TYPE);
+        contentValues.put(Nickname.NAME, "Nicky");
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, V30);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithOrder("NICKNAME", "Nicky");
+
+        verifyOneComposition(resolver, handler, V30);
+    }
+
+    private void testPhoneBasicCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "1");
+        contentValues.put(Phone.TYPE, Phone.TYPE_HOME);
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("TEL", "1", new TypeSet("HOME", "VOICE"));
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testPhoneBasicV21() {
+        testPhoneBasicCommon(V21);
+    }
+
+    public void testPhoneBasicV30() {
+        testPhoneBasicCommon(V30);
+    }
+
+    /**
+     * Tests that vCard composer emits corresponding type param which we expect.
+     */
+    private void testPhoneVariousTypeSupport(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "10");
+        contentValues.put(Phone.TYPE, Phone.TYPE_HOME);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "20");
+        contentValues.put(Phone.TYPE, Phone.TYPE_WORK);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "30");
+        contentValues.put(Phone.TYPE, Phone.TYPE_FAX_HOME);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "40");
+        contentValues.put(Phone.TYPE, Phone.TYPE_FAX_WORK);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "50");
+        contentValues.put(Phone.TYPE, Phone.TYPE_MOBILE);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "60");
+        contentValues.put(Phone.TYPE, Phone.TYPE_PAGER);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "70");
+        contentValues.put(Phone.TYPE, Phone.TYPE_OTHER);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "80");
+        contentValues.put(Phone.TYPE, Phone.TYPE_CAR);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "90");
+        contentValues.put(Phone.TYPE, Phone.TYPE_COMPANY_MAIN);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "100");
+        contentValues.put(Phone.TYPE, Phone.TYPE_ISDN);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "110");
+        contentValues.put(Phone.TYPE, Phone.TYPE_MAIN);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "120");
+        contentValues.put(Phone.TYPE, Phone.TYPE_OTHER_FAX);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "130");
+        contentValues.put(Phone.TYPE, Phone.TYPE_TELEX);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "140");
+        contentValues.put(Phone.TYPE, Phone.TYPE_WORK_MOBILE);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "150");
+        contentValues.put(Phone.TYPE, Phone.TYPE_WORK_PAGER);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "160");
+        contentValues.put(Phone.TYPE, Phone.TYPE_MMS);
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("TEL", "10", new TypeSet("HOME"))
+            .addNodeWithoutOrder("TEL", "20", new TypeSet("WORK"))
+            .addNodeWithoutOrder("TEL", "30", new TypeSet("HOME", "FAX"))
+            .addNodeWithoutOrder("TEL", "40", new TypeSet("WORK", "FAX"))
+            .addNodeWithoutOrder("TEL", "50", new TypeSet("CELL"))
+            .addNodeWithoutOrder("TEL", "60", new TypeSet("PAGER"))
+            .addNodeWithoutOrder("TEL", "70", new TypeSet("VOICE"))
+            .addNodeWithoutOrder("TEL", "80", new TypeSet("CAR"))
+            .addNodeWithoutOrder("TEL", "90", new TypeSet("WORK", "PREF"))
+            .addNodeWithoutOrder("TEL", "100", new TypeSet("ISDN"))
+            .addNodeWithoutOrder("TEL", "110", new TypeSet("PREF"))
+            .addNodeWithoutOrder("TEL", "120", new TypeSet("FAX"))
+            .addNodeWithoutOrder("TEL", "130", new TypeSet("TLX"))
+            .addNodeWithoutOrder("TEL", "140", new TypeSet("WORK", "MOBILE"))
+            .addNodeWithoutOrder("TEL", "150", new TypeSet("WORK", "PAGER"))
+            .addNodeWithoutOrder("TEL", "160", new TypeSet("MSG"));
+    }
+
+    public void testPhoneVariousTypeSupportV21() {
+        testPhoneVariousTypeSupport(V21);
+    }
+
+    public void testPhoneVariousTypeSupportV30() {
+        testPhoneVariousTypeSupport(V30);
+    }
+
+    /**
+     * Tests that "PREF"s are emitted appropriately.
+     */
+    private void testPhonePrefHandlingCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "1");
+        contentValues.put(Phone.TYPE, Phone.TYPE_HOME);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "2");
+        contentValues.put(Phone.TYPE, Phone.TYPE_WORK);
+        contentValues.put(Phone.IS_PRIMARY, 1);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "3");
+        contentValues.put(Phone.TYPE, Phone.TYPE_FAX_HOME);
+        contentValues.put(Phone.IS_PRIMARY, 1);
+
+        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
+        contentValues.put(Phone.NUMBER, "4");
+        contentValues.put(Phone.TYPE, Phone.TYPE_FAX_WORK);
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("TEL", "4", new TypeSet("WORK", "FAX"))
+            .addNodeWithoutOrder("TEL", "3", new TypeSet("HOME", "FAX", "PREF"))
+            .addNodeWithoutOrder("TEL", "2", new TypeSet("WORK", "VOICE", "PREF"))
+            .addNodeWithoutOrder("TEL", "1", new TypeSet("HOME", "VOICE"));
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testPhonePrefHandlingV21() {
+        testPhonePrefHandlingCommon(V21);
+    }
+
+    public void testPhonePrefHandlingV30() {
+        testPhonePrefHandlingCommon(V30);
+    }
+
+    private void testEmailBasicCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+        ContentValues contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
+        contentValues.put(Email.DATA, "sample@example.com");
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("EMAIL", "sample@example.com");
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testEmailBasicV21() {
+        testEmailBasicCommon(V21);
+    }
+
+    public void testEmailBasicV30() {
+        testEmailBasicCommon(V30);
+    }
+
+    private void testEmailVariousTypeSupportCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
+        contentValues.put(Email.DATA, "type_home@example.com");
+        contentValues.put(Email.TYPE, Email.TYPE_HOME);
+
+        contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
+        contentValues.put(Email.DATA, "type_work@example.com");
+        contentValues.put(Email.TYPE, Email.TYPE_WORK);
+
+        contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
+        contentValues.put(Email.DATA, "type_mobile@example.com");
+        contentValues.put(Email.TYPE, Email.TYPE_MOBILE);
+
+        contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
+        contentValues.put(Email.DATA, "type_other@example.com");
+        contentValues.put(Email.TYPE, Email.TYPE_OTHER);
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("EMAIL", "type_home@example.com", new TypeSet("HOME"))
+            .addNodeWithoutOrder("EMAIL", "type_work@example.com", new TypeSet("WORK"))
+            .addNodeWithoutOrder("EMAIL", "type_mobile@example.com", new TypeSet("CELL"))
+            .addNodeWithoutOrder("EMAIL", "type_other@example.com");
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testEmailVariousTypeSupportV21() {
+        testEmailVariousTypeSupportCommon(V21);
+    }
+
+    public void testEmailVariousTypeSupportV30() {
+        testEmailVariousTypeSupportCommon(V30);
+    }
+
+    private void testEmailPrefHandlingCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
+        contentValues.put(Email.DATA, "type_home@example.com");
+        contentValues.put(Email.TYPE, Email.TYPE_HOME);
+        contentValues.put(Email.IS_PRIMARY, 1);
+
+        contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
+        contentValues.put(Email.DATA, "type_notype@example.com");
+        contentValues.put(Email.IS_PRIMARY, 1);
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("EMAIL", "type_notype@example.com", new TypeSet("PREF"))
+            .addNodeWithoutOrder("EMAIL", "type_home@example.com", new TypeSet("HOME", "PREF"));
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testEmailPrefHandlingV21() {
+        testEmailPrefHandlingCommon(V21);
+    }
+
+    public void testEmailPrefHandlingV30() {
+        testEmailPrefHandlingCommon(V30);
+    }
+
+    private void testPostalOnlyWithStructuredDataCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        // adr-value    = 0*6(text-value ";") text-value
+        //              ; PO Box, Extended Address, Street, Locality, Region, Postal Code,
+        //              ; Country Name
+        ContentValues contentValues = resolver.buildData(StructuredPostal.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredPostal.POBOX, "Pobox");
+        contentValues.put(StructuredPostal.NEIGHBORHOOD, "Neighborhood");
+        contentValues.put(StructuredPostal.STREET, "Street");
+        contentValues.put(StructuredPostal.CITY, "City");
+        contentValues.put(StructuredPostal.REGION, "Region");
+        contentValues.put(StructuredPostal.POSTCODE, "100");
+        contentValues.put(StructuredPostal.COUNTRY, "Country");
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("ADR", "Pobox;Neighborhood;Street;City;Region;100;Country",
+                    Arrays.asList("Pobox", "Neighborhood", "Street", "City",
+                            "Region", "100", "Country"), new TypeSet("HOME"));
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testPostalOnlyWithStructuredDataV21() {
+        testPostalOnlyWithStructuredDataCommon(V21);
+    }
+
+    public void testPostalOnlyWithStructuredDataV30() {
+        testPostalOnlyWithStructuredDataCommon(V30);
+    }
+
+    private void testPostalOnlyWithFormattedAddressCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(StructuredPostal.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredPostal.FORMATTED_ADDRESS,
+                "Formatted address CA 123-334 United Statue");
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithOrder("ADR", ";Formatted address CA 123-334 United Statue;;;;;",
+                    Arrays.asList("", "Formatted address CA 123-334 United Statue",
+                            "", "", "", "", ""), new TypeSet("HOME"));
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testPostalOnlyWithFormattedAddressV21() {
+        testPostalOnlyWithFormattedAddressCommon(V21);
+    }
+
+    public void testPostalOnlyWithFormattedAddressV30() {
+        testPostalOnlyWithFormattedAddressCommon(V30);
+    }
+
+    /**
+     * Tests that the vCard composer honors formatted data when it is available
+     * even when it is partial.
+     */
+    private void testPostalWithBothStructuredAndFormattedCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(StructuredPostal.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredPostal.POBOX, "Pobox");
+        contentValues.put(StructuredPostal.COUNTRY, "Country");
+        contentValues.put(StructuredPostal.FORMATTED_ADDRESS,
+                "Formatted address CA 123-334 United Statue");  // Should be ignored
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("ADR", "Pobox;;;;;;Country",
+                    Arrays.asList("Pobox", "", "", "", "", "", "Country"), new TypeSet("HOME"));
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testPostalWithBothStructuredAndFormattedV21() {
+        testPostalWithBothStructuredAndFormattedCommon(V21);
+    }
+
+    public void testPostalWithBothStructuredAndFormattedV30() {
+        testPostalWithBothStructuredAndFormattedCommon(V30);
+    }
+
+    private void testOrganizationCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+        ContentValues contentValues = resolver.buildData(Organization.CONTENT_ITEM_TYPE);
+        contentValues.put(Organization.COMPANY, "CompanyX");
+        contentValues.put(Organization.DEPARTMENT, "DepartmentY");
+        contentValues.put(Organization.TITLE, "TitleZ");
+        contentValues.put(Organization.JOB_DESCRIPTION, "Description Rambda");  // Ignored.
+        contentValues.put(Organization.OFFICE_LOCATION, "Mountain View");  // Ignored.
+        contentValues.put(Organization.PHONETIC_NAME, "PhoneticName!");  // Ignored
+        contentValues.put(Organization.SYMBOL, "(^o^)/~~");  // Ignore him (her).
+
+        contentValues = resolver.buildData(Organization.CONTENT_ITEM_TYPE);
+        contentValues.putNull(Organization.COMPANY);
+        contentValues.put(Organization.DEPARTMENT, "DepartmentXX");
+        contentValues.putNull(Organization.TITLE);
+
+        contentValues = resolver.buildData(Organization.CONTENT_ITEM_TYPE);
+        contentValues.put(Organization.COMPANY, "CompanyXYZ");
+        contentValues.putNull(Organization.DEPARTMENT);
+        contentValues.put(Organization.TITLE, "TitleXYZYX");
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+
+        // Currently we do not use group but depend on the order.
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithOrder("ORG", "CompanyX;DepartmentY",
+                    Arrays.asList("CompanyX", "DepartmentY"))
+            .addNodeWithOrder("TITLE", "TitleZ")
+            .addNodeWithOrder("ORG", "DepartmentXX")
+            .addNodeWithOrder("ORG", "CompanyXYZ")
+            .addNodeWithOrder("TITLE", "TitleXYZYX");
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testOrganizationV21() {
+        testOrganizationCommon(V21);
+    }
+
+    public void testOrganizationV30() {
+        testOrganizationCommon(V30);
+    }
+
+    private void testImVariousTypeSupportCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_AIM);
+        contentValues.put(Im.DATA, "aim");
+
+        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_MSN);
+        contentValues.put(Im.DATA, "msn");
+
+        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_YAHOO);
+        contentValues.put(Im.DATA, "yahoo");
+
+        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_SKYPE);
+        contentValues.put(Im.DATA, "skype");
+
+        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_QQ);
+        contentValues.put(Im.DATA, "qq");
+
+        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
+        contentValues.put(Im.DATA, "google talk");
+
+        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_ICQ);
+        contentValues.put(Im.DATA, "icq");
+
+        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_JABBER);
+        contentValues.put(Im.DATA, "jabber");
+
+        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_NETMEETING);
+        contentValues.put(Im.DATA, "netmeeting");
+
+        // No determined way to express unknown type...
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("X-JABBER", "jabber")
+            .addNodeWithoutOrder("X-ICQ", "icq")
+            .addNodeWithoutOrder("X-GOOGLE-TALK", "google talk")
+            .addNodeWithoutOrder("X-QQ", "qq")
+            .addNodeWithoutOrder("X-SKYPE-USERNAME", "skype")
+            .addNodeWithoutOrder("X-YAHOO", "yahoo")
+            .addNodeWithoutOrder("X-MSN", "msn")
+            .addNodeWithoutOrder("X-NETMEETING", "netmeeting")
+            .addNodeWithoutOrder("X-AIM", "aim");
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testImBasiV21() {
+        testImVariousTypeSupportCommon(V21);
+    }
+
+    public void testImBasicV30() {
+        testImVariousTypeSupportCommon(V30);
+    }
+
+    private void testImPrefHandlingCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_AIM);
+        contentValues.put(Im.DATA, "aim1");
+
+        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
+        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_AIM);
+        contentValues.put(Im.DATA, "aim2");
+        contentValues.put(Im.TYPE, Im.TYPE_HOME);
+        contentValues.put(Im.IS_PRIMARY, 1);
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("X-AIM", "aim1")
+            .addNodeWithoutOrder("X-AIM", "aim2", new TypeSet("HOME", "PREF"));
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testImPrefHandlingV21() {
+        testImPrefHandlingCommon(V21);
+    }
+
+    public void testImPrefHandlingV30() {
+        testImPrefHandlingCommon(V30);
+    }
+
+    private void testWebsiteCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(Website.CONTENT_ITEM_TYPE);
+        contentValues.put(Website.URL, "http://website.example.android.com/index.html");
+        contentValues.put(Website.TYPE, Website.TYPE_BLOG);
+
+        contentValues = resolver.buildData(Website.CONTENT_ITEM_TYPE);
+        contentValues.put(Website.URL, "ftp://ftp.example.android.com/index.html");
+        contentValues.put(Website.TYPE, Website.TYPE_FTP);
+
+        // We drop TYPE information since vCard (especially 3.0) does not allow us to emit it.
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("URL", "ftp://ftp.example.android.com/index.html")
+            .addNodeWithoutOrder("URL", "http://website.example.android.com/index.html");
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testWebsiteV21() {
+        testWebsiteCommon(V21);
+    }
+
+    public void testWebsiteV30() {
+        testWebsiteCommon(V30);
+    }
+
+    private void testEventCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(Event.CONTENT_ITEM_TYPE);
+        contentValues.put(Event.TYPE, Event.TYPE_ANNIVERSARY);
+        contentValues.put(Event.START_DATE, "1982-06-16");
+
+        contentValues = resolver.buildData(Event.CONTENT_ITEM_TYPE);
+        contentValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
+        contentValues.put(Event.START_DATE, "2008-10-22");
+
+        contentValues = resolver.buildData(Event.CONTENT_ITEM_TYPE);
+        contentValues.put(Event.TYPE, Event.TYPE_OTHER);
+        contentValues.put(Event.START_DATE, "2018-03-12");
+
+        contentValues = resolver.buildData(Event.CONTENT_ITEM_TYPE);
+        contentValues.put(Event.TYPE, Event.TYPE_CUSTOM);
+        contentValues.put(Event.LABEL, "The last day");
+        contentValues.put(Event.START_DATE, "When the Tower of Hanoi with 64 rings is completed.");
+
+        contentValues = resolver.buildData(Event.CONTENT_ITEM_TYPE);
+        contentValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
+        contentValues.put(Event.START_DATE, "2009-05-19");
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithoutOrder("BDAY", "2008-10-22");
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testEventV21() {
+        testEventCommon(V21);
+    }
+
+    public void testEventV30() {
+        testEventCommon(V30);
+    }
+
+    private void testNoteCommon(int version) {
+        ExportTestResolver resolver = new ExportTestResolver();
+
+        ContentValues contentValues = resolver.buildData(Note.CONTENT_ITEM_TYPE);
+        contentValues.put(Note.NOTE, "note1");
+
+        contentValues = resolver.buildData(Note.CONTENT_ITEM_TYPE);
+        contentValues.put(Note.NOTE, "note2");
+        contentValues.put(Note.IS_PRIMARY, 1);  // Just ignored.
+
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifierWithEmptyName()
+            .addNodeWithOrder("NOTE", "note1")
+            .addNodeWithOrder("NOTE", "note2");
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
+    public void testNoteV21() {
+        testNoteCommon(V21);
+    }
+
+    public void testNoteV30() {
+        testNoteCommon(V30);
+    }
+
+    // TODO: test for non-ascii...
+
+    private void testPhotoCommon(int version) {
+        final boolean isV30 = version == V30;
+        ExportTestResolver resolver = new ExportTestResolver();
+        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
+        contentValues.put(StructuredName.FAMILY_NAME, "PhotoTest");
+
+        contentValues = resolver.buildData(Photo.CONTENT_ITEM_TYPE);
+        contentValues.put(Photo.PHOTO, sPhotoByteArray);
+
+        ContentValues contentValuesForPhoto = new ContentValues();
+        contentValuesForPhoto.put("ENCODING", (isV30 ? "b" : "BASE64"));
+        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        handler.addNewVerifier()
+            .addNodeWithoutOrder("FN", "PhotoTest")
+            .addNodeWithoutOrder("N", "PhotoTest;;;;", Arrays.asList("PhotoTest", "", "", "", ""))
+            .addNodeWithOrder("PHOTO", null, null, sPhotoByteArray,
+                    contentValuesForPhoto, new TypeSet("JPEG"), null);
+
+        verifyOneComposition(resolver, handler, version);
+    }
+
     public void testPhotoV21() {
-        testPhotoCommon(false);
+        testPhotoCommon(V21);
     }
 
     public void testPhotoV30() {
-        testPhotoCommon(true);
+        testPhotoCommon(V30);
     }
 }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java
index c6f827d..51bce72 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java
@@ -722,7 +722,7 @@
 
     public void testV21SimpleCase1_Type_Generic() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_simple_1, VCardConfig.VCARD_TYPE_V21_GENERIC);
+                R.raw.v21_simple_1, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         contentValues.put(StructuredName.FAMILY_NAME, "Ando");
@@ -733,7 +733,7 @@
 
     public void testV21SimpleCase1_Type_Japanese() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_simple_1, VCardConfig.VCARD_TYPE_V21_JAPANESE);
+                R.raw.v21_simple_1, VCardConfig.VCARD_TYPE_V21_JAPANESE_SJIS);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         contentValues.put(StructuredName.FAMILY_NAME, "Ando");
@@ -746,7 +746,7 @@
 
     public void testV21SimpleCase2() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_simple_2, VCardConfig.VCARD_TYPE_V21_GENERIC);
+                R.raw.v21_simple_2, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         contentValues.put(StructuredName.DISPLAY_NAME, "Ando Roid");
@@ -755,7 +755,7 @@
 
     public void testV21SimpleCase3() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_simple_3, VCardConfig.VCARD_TYPE_V21_GENERIC);
+                R.raw.v21_simple_3, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         contentValues.put(StructuredName.FAMILY_NAME, "Ando");
@@ -790,7 +790,7 @@
      */
     public void testV21BackslashCase() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_backslash, VCardConfig.VCARD_TYPE_V21_GENERIC);
+                R.raw.v21_backslash, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         // FAMILY_NAME is empty and removed in this test...
@@ -804,7 +804,7 @@
 
     public void testOrgBeforTitle() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_org_before_title, VCardConfig.VCARD_TYPE_V21_GENERIC);
+                R.raw.v21_org_before_title, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         contentValues.put(StructuredName.DISPLAY_NAME, "Normal Guy");
@@ -819,7 +819,7 @@
 
     public void testTitleBeforOrg() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_title_before_org, VCardConfig.VCARD_TYPE_V21_GENERIC);
+                R.raw.v21_title_before_org, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         contentValues.put(StructuredName.DISPLAY_NAME, "Nice Guy");
@@ -838,7 +838,7 @@
      */
     public void testV21PrefToIsPrimary() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_pref_handling, VCardConfig.VCARD_TYPE_V21_GENERIC);
+                R.raw.v21_pref_handling, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         contentValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
@@ -952,7 +952,7 @@
      */
     public void testV21ComplicatedCase() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_complicated, VCardConfig.VCARD_TYPE_V21_GENERIC);
+                R.raw.v21_complicated, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         contentValues.put(StructuredName.FAMILY_NAME, "Gump");
@@ -1068,7 +1068,7 @@
 
     public void testV30Simple() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v30_simple, VCardConfig.VCARD_TYPE_V30_GENERIC);
+                R.raw.v30_simple, VCardConfig.VCARD_TYPE_V30_GENERIC_UTF8);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         contentValues.put(StructuredName.FAMILY_NAME, "And");
@@ -1139,25 +1139,28 @@
         verifier.verify();
     }
     /**
-     * Verifies vCard with Japanese can be parsed correctly with VCARD_TYPE_V21_GENERIC. 
+     * Verifies vCard with Japanese can be parsed correctly with
+     * {@link android.pim.vcard.VCardConfig#VCARD_TYPE_V21_GENERIC_UTF8}.
      */
-    public void testV21Japanese1_Type_Generic() throws IOException, VCardException {
+    public void testV21Japanese1_Type_Generic_Utf8() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_japanese_1, VCardConfig.VCARD_TYPE_V21_GENERIC);
+                R.raw.v21_japanese_1, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         testV21Japanese1Common(verifier, false);
     }
 
     /**
-     * Verifies vCard with Japanese can be parsed correctly with VCARD_TYPE_V21_JAPANESE.
+     * Verifies vCard with Japanese can be parsed correctly with
+     * {@link android.pim.vcard.VCardConfig#VCARD_TYPE_V21_JAPANESE_SJIS}.
      */
-    public void testV21Japanese1_Type_Japanese() throws IOException, VCardException {
+    public void testV21Japanese1_Type_Japanese_Sjis() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_japanese_1, VCardConfig.VCARD_TYPE_V21_JAPANESE);
+                R.raw.v21_japanese_1, VCardConfig.VCARD_TYPE_V21_JAPANESE_SJIS);
         testV21Japanese1Common(verifier, true);
     }
 
     /**
-     * Verifies vCard with Japanese can be parsed correctly with VCARD_TYPE_V21_JAPANESE_UTF8,
+     * Verifies vCard with Japanese can be parsed correctly with
+     * {@link android.pim.vcard.VCardConfig#VCARD_TYPE_V21_JAPANESE_UTF8}.
      * since vCard 2.1 specifies the charset of each line if it contains non-Ascii.
      */
     public void testV21Japanese1_Type_Japanese_Utf8() throws IOException, VCardException {
@@ -1205,9 +1208,9 @@
         verifier.verify(builder.vNodeList.get(0));
     }
 
-    public void testV21Japanese2_Type_Generic() throws IOException, VCardException {
+    public void testV21Japanese2_Type_Generic_Utf8() throws IOException, VCardException {
         ContactStructVerifier verifier = new ContactStructVerifier(
-                R.raw.v21_japanese_2, VCardConfig.VCARD_TYPE_V21_GENERIC);
+                R.raw.v21_japanese_2, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
         ContentValues contentValues =
             verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
         contentValues.put(StructuredName.FAMILY_NAME, "\u5B89\u85E4");
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 395e572..32219fa 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -79,8 +79,7 @@
         "profiler",  // profiler is not supported
         "svg",  // svg is not supported
         "platform",  // platform specific
-        "http",  // requires local http(s) server
-        "fast/workers",
+        "http/wml",
     };
         
     static final String [] ignoreTestList = {
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index 234e5b2..1ac13f2 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -80,11 +80,13 @@
     void setValues(bool val) { mValues = val; }
     int getCompressionMethod(void) const { return mCompressionMethod; }
     void setCompressionMethod(int val) { mCompressionMethod = val; }
+    bool getJunkPath(void) const { return mJunkPath; }
+    void setJunkPath(bool val) { mJunkPath = val; }
     const char* getOutputAPKFile() const { return mOutputAPKFile; }
     void setOutputAPKFile(const char* val) { mOutputAPKFile = val; }
 
-    /*                                                                
-     * Input options.                                                                
+    /*
+     * Input options.
      */
     const char* getAssetSourceDir() const { return mAssetSourceDir; }
     void setAssetSourceDir(const char* dir) { mAssetSourceDir = dir; }
@@ -119,7 +121,7 @@
     void setVersionCode(const char*  val) { mVersionCode = val; }
     const char* getVersionName() const { return mVersionName; }
     void setVersionName(const char* val) { mVersionName = val; }
-    
+
     /*
      * Set and get the file specification.
      *
@@ -161,6 +163,7 @@
     bool        mPseudolocalize;
     bool        mValues;
     int         mCompressionMethod;
+    bool        mJunkPath;
     const char* mOutputAPKFile;
     const char* mAssetSourceDir;
     const char* mProguardFile;
@@ -173,13 +176,13 @@
     android::Vector<const char*> mJarFiles;
     android::Vector<const char*> mNoCompressExtensions;
     android::Vector<const char*> mResourceSourceDirs;
-    
+
     const char* mMinSdkVersion;
     const char* mTargetSdkVersion;
     const char* mMaxSdkVersion;
     const char* mVersionCode;
     const char* mVersionName;
-    
+
     /* file specification */
     int         mArgc;
     char* const* mArgv;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 4742341..1a536d6 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -848,7 +848,7 @@
                 printf("uses-feature:'android.hardware.camera'\n");
                 printf("uses-feature:'android.hardware.camera.autofocus'\n");
             }
-            
+
             if (hasMainActivity) {
                 printf("main\n");
             }
@@ -997,8 +997,15 @@
             printf(" '%s'... (from gzip)\n", fileName);
             result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL);
         } else {
-            printf(" '%s'...\n", fileName);
-            result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
+            if (bundle->getJunkPath()) {
+                String8 storageName = String8(fileName).getPathLeaf();
+                printf(" '%s' as '%s'...\n", fileName, storageName.string());
+                result = zip->add(fileName, storageName.string(),
+                                  bundle->getCompressionMethod(), NULL);
+            } else {
+                printf(" '%s'...\n", fileName);
+                result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
+            }
         }
         if (result != NO_ERROR) {
             fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName);
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index e61010c..98286c0 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -99,6 +99,7 @@
         "   -f  force overwrite of existing files\n"
         "   -g  specify a pixel tolerance to force images to grayscale, default 0\n"
         "   -j  specify a jar or zip file containing classes to include\n"
+        "   -k  junk path of file(s) added\n"
         "   -m  make package directories under location specified by -J\n"
 #if 0
         "   -p  pseudolocalize the default configuration\n"
@@ -236,6 +237,9 @@
                 bundle.setGrayscaleTolerance(tolerance);
                 printf("%s: Images with deviation <= %d will be forced to grayscale.\n", prog, tolerance);
                 break;
+            case 'k':
+                bundle.setJunkPath(true);
+                break;
             case 'm':
                 bundle.setMakePackageDirs(true);
                 break;