Merge "Expose Adapter."
diff --git a/api/current.xml b/api/current.xml
index 715b49a..8d8e96f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -26632,7 +26632,7 @@
 <parameter name="mimeType" type="java.lang.String">
 </parameter>
 </method>
-<method name="setShowRunningNotification"
+<method name="setNotificationVisibility"
  return="android.app.DownloadManager.Request"
  abstract="false"
  native="false"
@@ -26642,6 +26642,19 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="visibility" type="int">
+</parameter>
+</method>
+<method name="setShowRunningNotification"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
 <parameter name="show" type="boolean">
 </parameter>
 </method>
@@ -26693,6 +26706,39 @@
  visibility="public"
 >
 </field>
+<field name="VISIBILITY_HIDDEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VISIBILITY_VISIBLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VISIBILITY_VISIBLE_NOTIFY_COMPLETED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="ExpandableListActivity"
  extends="android.app.Activity"
@@ -40186,6 +40232,17 @@
 <parameter name="makeMap" type="boolean">
 </parameter>
 </method>
+<method name="goAsync"
+ return="android.content.BroadcastReceiver.PendingResult"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isInitialStickyBroadcast"
  return="boolean"
  abstract="false"
@@ -40321,14 +40378,160 @@
 </parameter>
 </method>
 </class>
+<class name="BroadcastReceiver.PendingResult"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="abortBroadcast"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="clearAbortBroadcast"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="finish"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAbortBroadcast"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getResultCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getResultData"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getResultExtras"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="makeMap" type="boolean">
+</parameter>
+</method>
+<method name="setResult"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="code" type="int">
+</parameter>
+<parameter name="data" type="java.lang.String">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="setResultCode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="code" type="int">
+</parameter>
+</method>
+<method name="setResultData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="java.lang.String">
+</parameter>
+</method>
+<method name="setResultExtras"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+</method>
+</class>
 <class name="ClipData"
- extends="android.content.ClipDescription"
+ extends="java.lang.Object"
  abstract="false"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.os.Parcelable">
+</implements>
 <constructor name="ClipData"
  type="android.content.ClipData"
  static="false"
@@ -40345,6 +40548,20 @@
 <parameter name="item" type="android.content.ClipData.Item">
 </parameter>
 </constructor>
+<constructor name="ClipData"
+ type="android.content.ClipData"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="description" type="android.content.ClipDescription">
+</parameter>
+<parameter name="icon" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="item" type="android.content.ClipData.Item">
+</parameter>
+</constructor>
 <method name="addItem"
  return="void"
  abstract="false"
@@ -40358,6 +40575,28 @@
 <parameter name="item" type="android.content.ClipData.Item">
 </parameter>
 </method>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDescription"
+ return="android.content.ClipDescription"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getIcon"
  return="android.graphics.Bitmap"
  abstract="false"
@@ -40463,6 +40702,21 @@
 <parameter name="uri" type="android.net.Uri">
 </parameter>
 </method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
 <field name="CREATOR"
  type="android.os.Parcelable.Creator"
  transient="false"
@@ -113165,7 +113419,7 @@
  extends="java.lang.Object"
  abstract="false"
  static="false"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -113256,7 +113510,7 @@
  extends="java.lang.Object"
  abstract="false"
  static="false"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -113536,273 +113790,6 @@
 >
 </field>
 </class>
-<class name="NdefTag"
- extends="android.nfc.Tag"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.os.Parcelable">
-</implements>
-<method name="createMockNdefTag"
- return="android.nfc.NdefTag"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="byte[]">
-</parameter>
-<parameter name="rawTargets" type="java.lang.String[]">
-</parameter>
-<parameter name="pollBytes" type="byte[]">
-</parameter>
-<parameter name="activationBytes" type="byte[]">
-</parameter>
-<parameter name="ndefTargets" type="java.lang.String[]">
-</parameter>
-<parameter name="messages" type="android.nfc.NdefMessage[][]">
-</parameter>
-</method>
-<method name="getNdefMessages"
- return="android.nfc.NdefMessage[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getNdefMessages"
- return="android.nfc.NdefMessage[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="target" type="java.lang.String">
-</parameter>
-</method>
-<method name="getNdefTargets"
- return="java.lang.String[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<field name="CREATOR"
- type="android.os.Parcelable.Creator"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_MIFARE_CLASSIC"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;type_mifare_classic&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_OTHER"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;other&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_TYPE_1"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;type_1&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_TYPE_2"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;type_2&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_TYPE_3"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;type_3&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_TYPE_4"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;type_4&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-<class name="NdefTagConnection"
- extends="android.nfc.RawTagConnection"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="getModeHint"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
-<method name="makeReadOnly"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
-<method name="readNdefMessages"
- return="android.nfc.NdefMessage[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="FormatException" type="android.nfc.FormatException">
-</exception>
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
-<method name="writeNdefMessage"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="message" type="android.nfc.NdefMessage">
-</parameter>
-<exception name="FormatException" type="android.nfc.FormatException">
-</exception>
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
-<field name="NDEF_MODE_READ_ONCE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NDEF_MODE_READ_ONLY"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NDEF_MODE_UNKNOWN"
- type="int"
- transient="false"
- volatile="false"
- value="5"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NDEF_MODE_WRITE_MANY"
- type="int"
- transient="false"
- volatile="false"
- value="4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NDEF_MODE_WRITE_ONCE"
- type="int"
- transient="false"
- volatile="false"
- value="3"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
 <class name="NfcAdapter"
  extends="java.lang.Object"
  abstract="false"
@@ -113811,62 +113798,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<method name="createNdefTagConnection"
- return="android.nfc.NdefTagConnection"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="tag" type="android.nfc.NdefTag">
-</parameter>
-</method>
-<method name="createNdefTagConnection"
- return="android.nfc.NdefTagConnection"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="tag" type="android.nfc.NdefTag">
-</parameter>
-<parameter name="target" type="java.lang.String">
-</parameter>
-</method>
-<method name="createRawTagConnection"
- return="android.nfc.RawTagConnection"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="tag" type="android.nfc.Tag">
-</parameter>
-</method>
-<method name="createRawTagConnection"
- return="android.nfc.RawTagConnection"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="tag" type="android.nfc.Tag">
-</parameter>
-<parameter name="target" type="java.lang.String">
-</parameter>
-</method>
 <method name="getDefaultAdapter"
  return="android.nfc.NfcAdapter"
  abstract="false"
@@ -113878,17 +113809,6 @@
  visibility="public"
 >
 </method>
-<method name="getLocalNdefMessage"
- return="android.nfc.NdefMessage"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="isEnabled"
  return="boolean"
  abstract="false"
@@ -113900,30 +113820,6 @@
  visibility="public"
 >
 </method>
-<method name="setLocalNdefMessage"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="message" type="android.nfc.NdefMessage">
-</parameter>
-</method>
-<field name="ACTION_NDEF_TAG_DISCOVERED"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.nfc.action.NDEF_TAG_DISCOVERED&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="ACTION_TAG_DISCOVERED"
  type="java.lang.String"
  transient="false"
@@ -113935,268 +113831,22 @@
  visibility="public"
 >
 </field>
-<field name="EXTRA_TAG"
+<field name="EXTRA_ID"
  type="java.lang.String"
  transient="false"
  volatile="false"
- value="&quot;android.nfc.extra.TAG&quot;"
+ value="&quot;android.nfc.extra.ID&quot;"
  static="true"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
 </field>
-</class>
-<class name="RawTagConnection"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="close"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="connect"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
-<method name="getTag"
- return="android.nfc.Tag"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getTagTarget"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="isConnected"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="transceive"
- return="byte[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="data" type="byte[]">
-</parameter>
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
-</class>
-<class name="Tag"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.os.Parcelable">
-</implements>
-<method name="createMockTag"
- return="android.nfc.Tag"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="byte[]">
-</parameter>
-<parameter name="rawTargets" type="java.lang.String[]">
-</parameter>
-<parameter name="pollBytes" type="byte[]">
-</parameter>
-<parameter name="activationBytes" type="byte[]">
-</parameter>
-</method>
-<method name="describeContents"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getActivationBytes"
- return="byte[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getId"
- return="byte[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getPollBytes"
- return="byte[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getRawTargets"
- return="java.lang.String[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="writeToParcel"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="dest" type="android.os.Parcel">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
-<field name="CREATOR"
- type="android.os.Parcelable.Creator"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_ISO_14443_3A"
+<field name="EXTRA_NDEF_MESSAGES"
  type="java.lang.String"
  transient="false"
  volatile="false"
- value="&quot;iso14443_3a&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_ISO_14443_3B"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;iso14443_3b&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_ISO_14443_4"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;iso14443_4&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_ISO_15693"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;iso15693&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_JIS_X_6319_4"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;jis_x_6319_4&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TARGET_OTHER"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;other&quot;"
+ value="&quot;android.nfc.extra.NDEF_MESSAGES&quot;"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -134527,6 +134177,17 @@
 <parameter name="key" type="java.lang.String">
 </parameter>
 </method>
+<method name="getClassLoader"
+ return="java.lang.ClassLoader"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDouble"
  return="double"
  abstract="false"
@@ -138974,6 +138635,23 @@
 >
 </field>
 </class>
+<class name="NetworkOnMainThreadException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="NetworkOnMainThreadException"
+ type="android.os.NetworkOnMainThreadException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+</class>
 <class name="Parcel"
  extends="java.lang.Object"
  abstract="false"
@@ -142085,6 +141763,17 @@
  visibility="public"
 >
 </method>
+<method name="penaltyDeathOnNetwork"
+ return="android.os.StrictMode.ThreadPolicy.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="penaltyDialog"
  return="android.os.StrictMode.ThreadPolicy.Builder"
  abstract="false"
@@ -145346,23 +145035,6 @@
 <parameter name="header" type="android.preference.PreferenceActivity.Header">
 </parameter>
 </method>
-<method name="switchToHeaderInner"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="fragmentName" type="java.lang.String">
-</parameter>
-<parameter name="args" type="android.os.Bundle">
-</parameter>
-<parameter name="next" type="boolean">
-</parameter>
-</method>
 <field name="EXTRA_NO_HEADERS"
  type="java.lang.String"
  transient="false"
@@ -151593,6 +151265,36 @@
 </implements>
 <implements name="android.provider.ContactsContract.DataColumnsWithJoins">
 </implements>
+<method name="getTypeLabel"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="label" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="getTypeLabelResource"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="int">
+</parameter>
+</method>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -158649,6 +158351,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_INPUT_METHOD_AND_SUBTYPE_ENABLER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.settings.INPUT_METHOD_AND_SUBTYPE_ENABLER&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_INPUT_METHOD_SETTINGS"
  type="java.lang.String"
  transient="false"
@@ -160706,7 +160419,7 @@
  value="&quot;show_web_suggestions&quot;"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -218019,6 +217732,17 @@
 <parameter name="completions" type="android.view.inputmethod.CompletionInfo[]">
 </parameter>
 </method>
+<method name="getCurrentInputMethodSubtype"
+ return="android.view.inputmethod.InputMethodSubtype"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getEnabledInputMethodList"
  return="java.util.List&lt;android.view.inputmethod.InputMethodInfo&gt;"
  abstract="false"
@@ -245381,7 +245105,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index e269c31..ad8c971 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -83,15 +83,61 @@
      */
     private long mSeekTime = -1;
 
+    // TODO: We access the following ThreadLocal variables often, some of them on every update.
+    // If ThreadLocal access is significantly expensive, we may want to put all of these
+    // fields into a structure sot hat we just access ThreadLocal once to get the reference
+    // to that structure, then access the structure directly for each field.
+
     // The static sAnimationHandler processes the internal timing loop on which all animations
     // are based
-    private static AnimationHandler sAnimationHandler;
+    private static ThreadLocal<AnimationHandler> sAnimationHandler =
+            new ThreadLocal<AnimationHandler>();
 
-    // The static list of all active animations
-    private static final ArrayList<ValueAnimator> sAnimations = new ArrayList<ValueAnimator>();
+    // The per-thread list of all active animations
+    private static final ThreadLocal<ArrayList<ValueAnimator>> sAnimations =
+            new ThreadLocal<ArrayList<ValueAnimator>>() {
+                @Override
+                protected ArrayList<ValueAnimator> initialValue() {
+                    return new ArrayList<ValueAnimator>();
+                }
+            };
 
-    // The set of animations to be started on the next animation frame
-    private static final ArrayList<ValueAnimator> sPendingAnimations = new ArrayList<ValueAnimator>();
+    // The per-thread set of animations to be started on the next animation frame
+    private static final ThreadLocal<ArrayList<ValueAnimator>> sPendingAnimations =
+            new ThreadLocal<ArrayList<ValueAnimator>>() {
+                @Override
+                protected ArrayList<ValueAnimator> initialValue() {
+                    return new ArrayList<ValueAnimator>();
+                }
+            };
+
+    /**
+     * Internal per-thread collections used to avoid set collisions as animations start and end
+     * while being processed.
+     */
+    private static final ThreadLocal<ArrayList<ValueAnimator>> sDelayedAnims =
+            new ThreadLocal<ArrayList<ValueAnimator>>() {
+                @Override
+                protected ArrayList<ValueAnimator> initialValue() {
+                    return new ArrayList<ValueAnimator>();
+                }
+            };
+
+    private static final ThreadLocal<ArrayList<ValueAnimator>> sEndingAnims =
+            new ThreadLocal<ArrayList<ValueAnimator>>() {
+                @Override
+                protected ArrayList<ValueAnimator> initialValue() {
+                    return new ArrayList<ValueAnimator>();
+                }
+            };
+
+    private static final ThreadLocal<ArrayList<ValueAnimator>> sReadyAnims =
+            new ThreadLocal<ArrayList<ValueAnimator>>() {
+                @Override
+                protected ArrayList<ValueAnimator> initialValue() {
+                    return new ArrayList<ValueAnimator>();
+                }
+            };
 
     // The time interpolator to be used if none is set on the animation
     private static final TimeInterpolator sDefaultInterpolator =
@@ -136,14 +182,6 @@
     private int mPlayingState = STOPPED;
 
     /**
-     * Internal collections used to avoid set collisions as animations start and end while being
-     * processed.
-     */
-    private static final ArrayList<ValueAnimator> sEndingAnims = new ArrayList<ValueAnimator>();
-    private static final ArrayList<ValueAnimator> sDelayedAnims = new ArrayList<ValueAnimator>();
-    private static final ArrayList<ValueAnimator> sReadyAnims = new ArrayList<ValueAnimator>();
-
-    /**
      * Flag that denotes whether the animation is set up and ready to go. Used to
      * set up animation that has not yet been started.
      */
@@ -609,11 +647,14 @@
         @Override
         public void handleMessage(Message msg) {
             boolean callAgain = true;
+            ArrayList<ValueAnimator> animations = sAnimations.get();
+            ArrayList<ValueAnimator> delayedAnims = sDelayedAnims.get();
             switch (msg.what) {
                 // TODO: should we avoid sending frame message when starting if we
                 // were already running?
                 case ANIMATION_START:
-                    if (sAnimations.size() > 0 || sDelayedAnims.size() > 0) {
+                    ArrayList<ValueAnimator> pendingAnimations = sPendingAnimations.get();
+                    if (animations.size() > 0 || delayedAnims.size() > 0) {
                         callAgain = false;
                     }
                     // pendingAnims holds any animations that have requested to be started
@@ -621,10 +662,10 @@
                     // cause more to be added to the pending list (for example, if one animation
                     // starting triggers another starting). So we loop until sPendingAnimations
                     // is empty.
-                    while (sPendingAnimations.size() > 0) {
+                    while (pendingAnimations.size() > 0) {
                         ArrayList<ValueAnimator> pendingCopy =
-                                (ArrayList<ValueAnimator>) sPendingAnimations.clone();
-                        sPendingAnimations.clear();
+                                (ArrayList<ValueAnimator>) pendingAnimations.clone();
+                        pendingAnimations.clear();
                         int count = pendingCopy.size();
                         for (int i = 0; i < count; ++i) {
                             ValueAnimator anim = pendingCopy.get(i);
@@ -633,7 +674,7 @@
                                     anim.mPlayingState == CANCELED) {
                                 anim.startAnimation();
                             } else {
-                                sDelayedAnims.add(anim);
+                                delayedAnims.add(anim);
                             }
                         }
                     }
@@ -642,45 +683,47 @@
                     // currentTime holds the common time for all animations processed
                     // during this frame
                     long currentTime = AnimationUtils.currentAnimationTimeMillis();
+                    ArrayList<ValueAnimator> readyAnims = sReadyAnims.get();
+                    ArrayList<ValueAnimator> endingAnims = sEndingAnims.get();
 
                     // First, process animations currently sitting on the delayed queue, adding
                     // them to the active animations if they are ready
-                    int numDelayedAnims = sDelayedAnims.size();
+                    int numDelayedAnims = delayedAnims.size();
                     for (int i = 0; i < numDelayedAnims; ++i) {
-                        ValueAnimator anim = sDelayedAnims.get(i);
+                        ValueAnimator anim = delayedAnims.get(i);
                         if (anim.delayedAnimationFrame(currentTime)) {
-                            sReadyAnims.add(anim);
+                            readyAnims.add(anim);
                         }
                     }
-                    int numReadyAnims = sReadyAnims.size();
+                    int numReadyAnims = readyAnims.size();
                     if (numReadyAnims > 0) {
                         for (int i = 0; i < numReadyAnims; ++i) {
-                            ValueAnimator anim = sReadyAnims.get(i);
+                            ValueAnimator anim = readyAnims.get(i);
                             anim.startAnimation();
-                            sDelayedAnims.remove(anim);
+                            delayedAnims.remove(anim);
                         }
-                        sReadyAnims.clear();
+                        readyAnims.clear();
                     }
 
                     // Now process all active animations. The return value from animationFrame()
                     // tells the handler whether it should now be ended
-                    int numAnims = sAnimations.size();
+                    int numAnims = animations.size();
                     for (int i = 0; i < numAnims; ++i) {
-                        ValueAnimator anim = sAnimations.get(i);
+                        ValueAnimator anim = animations.get(i);
                         if (anim.animationFrame(currentTime)) {
-                            sEndingAnims.add(anim);
+                            endingAnims.add(anim);
                         }
                     }
-                    if (sEndingAnims.size() > 0) {
-                        for (int i = 0; i < sEndingAnims.size(); ++i) {
-                            sEndingAnims.get(i).endAnimation();
+                    if (endingAnims.size() > 0) {
+                        for (int i = 0; i < endingAnims.size(); ++i) {
+                            endingAnims.get(i).endAnimation();
                         }
-                        sEndingAnims.clear();
+                        endingAnims.clear();
                     }
 
                     // If there are still active or delayed animations, call the handler again
                     // after the frameDelay
-                    if (callAgain && (!sAnimations.isEmpty() || !sDelayedAnims.isEmpty())) {
+                    if (callAgain && (!animations.isEmpty() || !delayedAnims.isEmpty())) {
                         sendEmptyMessageDelayed(ANIMATION_FRAME, Math.max(0, sFrameDelay -
                             (AnimationUtils.currentAnimationTimeMillis() - currentTime)));
                     }
@@ -935,13 +978,13 @@
         mCurrentIteration = 0;
         mPlayingState = STOPPED;
         mStartedDelay = false;
-        sPendingAnimations.add(this);
-        if (sAnimationHandler == null) {
-            sAnimationHandler = new AnimationHandler();
+        sPendingAnimations.get().add(this);
+        AnimationHandler animationHandler = sAnimationHandler.get();
+        if (animationHandler == null) {
+            animationHandler = new AnimationHandler();
+            sAnimationHandler.set(animationHandler);
         }
-        // TODO: does this put too many messages on the queue if the handler
-        // is already running?
-        sAnimationHandler.sendEmptyMessage(ANIMATION_START);
+        animationHandler.sendEmptyMessage(ANIMATION_START);
     }
 
     @Override
@@ -965,14 +1008,16 @@
 
     @Override
     public void end() {
-        if (!sAnimations.contains(this) && !sPendingAnimations.contains(this)) {
+        if (!sAnimations.get().contains(this) && !sPendingAnimations.get().contains(this)) {
             // Special case if the animation has not yet started; get it ready for ending
             mStartedDelay = false;
-            sPendingAnimations.add(this);
-            if (sAnimationHandler == null) {
-                sAnimationHandler = new AnimationHandler();
+            sPendingAnimations.get().add(this);
+            AnimationHandler animationHandler = sAnimationHandler.get();
+            if (animationHandler == null) {
+                animationHandler = new AnimationHandler();
+                sAnimationHandler.set(animationHandler);
             }
-            sAnimationHandler.sendEmptyMessage(ANIMATION_START);
+            animationHandler.sendEmptyMessage(ANIMATION_START);
         }
         // Just set the ENDED flag - this causes the animation to end the next time a frame
         // is processed.
@@ -1009,7 +1054,7 @@
      * called on the UI thread.
      */
     private void endAnimation() {
-        sAnimations.remove(this);
+        sAnimations.get().remove(this);
         mPlayingState = STOPPED;
         if (mListeners != null) {
             ArrayList<AnimatorListener> tmpListeners =
@@ -1026,7 +1071,7 @@
      */
     private void startAnimation() {
         initAnimation();
-        sAnimations.add(this);
+        sAnimations.get().add(this);
         if (mStartDelay > 0 && mListeners != null) {
             // Listeners were already notified in start() if startDelay is 0; this is
             // just for delayed animations
@@ -1225,6 +1270,6 @@
      * @hide
      */
     public static int getCurrentAnimationsCount() {
-        return sAnimations.size();
+        return sAnimations.get().size();
     }
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 378a8bd..33f88d8 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1228,7 +1228,6 @@
      */
     protected void onPause() {
         mCalled = true;
-        QueuedWork.waitToFinish();
     }
 
     /**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2abe822..7315f01 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -117,12 +117,14 @@
  * {@hide}
  */
 public final class ActivityThread {
-    static final String TAG = "ActivityThread";
+    /** @hide */
+    public static final String TAG = "ActivityThread";
     private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
     private static final boolean DEBUG = false;
     static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
     static final boolean DEBUG_MESSAGES = false;
-    static final boolean DEBUG_BROADCAST = false;
+    /** @hide */
+    public static final boolean DEBUG_BROADCAST = false;
     private static final boolean DEBUG_RESULTS = false;
     private static final boolean DEBUG_BACKUP = false;
     private static final boolean DEBUG_CONFIGURATION = false;
@@ -262,18 +264,20 @@
         }
     }
 
-    private static final class ReceiverData {
+    private static final class ReceiverData extends BroadcastReceiver.PendingResult {
+        public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
+                boolean ordered, boolean sticky, IBinder token) {
+            super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token);
+            this.intent = intent;
+        }
+        
         Intent intent;
         ActivityInfo info;
-        int resultCode;
-        String resultData;
-        Bundle resultExtras;
-        boolean sync;
-        boolean resultAbort;
         public String toString() {
             return "ReceiverData{intent=" + intent + " packageName=" +
-            info.packageName + " resultCode=" + resultCode
-            + " resultData=" + resultData + " resultExtras=" + resultExtras + "}";
+                    info.packageName + " resultCode=" + getResultCode()
+                    + " resultData=" + getResultData() + " resultExtras="
+                    + getResultExtras(false) + "}";
         }
     }
 
@@ -466,15 +470,9 @@
 
         public final void scheduleReceiver(Intent intent, ActivityInfo info,
                 int resultCode, String data, Bundle extras, boolean sync) {
-            ReceiverData r = new ReceiverData();
-
-            r.intent = intent;
+            ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
+                    sync, false, mAppThread.asBinder());
             r.info = info;
-            r.resultCode = resultCode;
-            r.resultData = data;
-            r.resultExtras = extras;
-            r.sync = sync;
-
             queueOrSendMessage(H.RECEIVER, r);
         }
 
@@ -1799,18 +1797,12 @@
         try {
             java.lang.ClassLoader cl = packageInfo.getClassLoader();
             data.intent.setExtrasClassLoader(cl);
-            if (data.resultExtras != null) {
-                data.resultExtras.setClassLoader(cl);
-            }
+            data.setExtrasClassLoader(cl);
             receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
         } catch (Exception e) {
-            try {
-                if (DEBUG_BROADCAST) Slog.i(TAG,
-                        "Finishing failed broadcast to " + data.intent.getComponent());
-                mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
-                                   data.resultData, data.resultExtras, data.resultAbort);
-            } catch (RemoteException ex) {
-            }
+            if (DEBUG_BROADCAST) Slog.i(TAG,
+                    "Finishing failed broadcast to " + data.intent.getComponent());
+            data.sendFinished(mgr);
             throw new RuntimeException(
                 "Unable to instantiate receiver " + component
                 + ": " + e.toString(), e);
@@ -1828,20 +1820,13 @@
                 + ", dir=" + packageInfo.getAppDir());
 
             ContextImpl context = (ContextImpl)app.getBaseContext();
-            receiver.setOrderedHint(true);
-            receiver.setResult(data.resultCode, data.resultData,
-                data.resultExtras);
-            receiver.setOrderedHint(data.sync);
+            receiver.setPendingResult(data);
             receiver.onReceive(context.getReceiverRestrictedContext(),
                     data.intent);
         } catch (Exception e) {
-            try {
-                if (DEBUG_BROADCAST) Slog.i(TAG,
-                        "Finishing failed broadcast to " + data.intent.getComponent());
-                mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
-                    data.resultData, data.resultExtras, data.resultAbort);
-            } catch (RemoteException ex) {
-            }
+            if (DEBUG_BROADCAST) Slog.i(TAG,
+                    "Finishing failed broadcast to " + data.intent.getComponent());
+            data.sendFinished(mgr);
             if (!mInstrumentation.onException(receiver, e)) {
                 throw new RuntimeException(
                     "Unable to start receiver " + component
@@ -1849,22 +1834,8 @@
             }
         }
 
-        QueuedWork.waitToFinish();
-
-        try {
-            if (data.sync) {
-                if (DEBUG_BROADCAST) Slog.i(TAG,
-                        "Finishing ordered broadcast to " + data.intent.getComponent());
-                mgr.finishReceiver(
-                    mAppThread.asBinder(), receiver.getResultCode(),
-                    receiver.getResultData(), receiver.getResultExtras(false),
-                        receiver.getAbortBroadcast());
-            } else {
-                if (DEBUG_BROADCAST) Slog.i(TAG,
-                        "Finishing broadcast to " + data.intent.getComponent());
-                mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false);
-            }
-        } catch (RemoteException ex) {
+        if (receiver.getPendingResult() != null) {
+            data.finish();
         }
     }
 
@@ -2347,6 +2318,9 @@
             r.activity.mConfigChangeFlags |= configChanges;
             Bundle state = performPauseActivity(token, finished, true);
 
+            // Make sure any pending writes are now committed.
+            QueuedWork.waitToFinish();
+            
             // Tell the activity manager we have paused.
             try {
                 ActivityManagerNative.getDefault().activityPaused(token, state);
@@ -3214,6 +3188,17 @@
         }
 
         /**
+         * For apps targetting SDK Honeycomb or later, we don't allow
+         * network usage on the main event loop / UI thread.
+         *
+         * Note to those grepping:  this is what ultimately throws
+         * NetworkOnMainThreadException ...
+         */
+        if (data.appInfo.targetSdkVersion > 9) {
+            StrictMode.enableDeathOnNetwork();
+        }
+
+        /**
          * Switch this process to density compatibility mode if needed.
          */
         if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 5654599..570e494 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -26,7 +26,6 @@
 import android.net.Uri;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
-import android.provider.BaseColumns;
 import android.provider.Downloads;
 import android.util.Pair;
 
@@ -337,13 +336,34 @@
         private List<Pair<String, String>> mRequestHeaders = new ArrayList<Pair<String, String>>();
         private CharSequence mTitle;
         private CharSequence mDescription;
-        private boolean mShowNotification = true;
         private String mMimeType;
         private boolean mRoamingAllowed = true;
         private int mAllowedNetworkTypes = ~0; // default to all network types allowed
         private boolean mIsVisibleInDownloadsUi = true;
 
         /**
+         * This download is visible but only shows in the notifications
+         * while it's in progress.
+         */
+        public static final int VISIBILITY_VISIBLE = 0;
+
+        /**
+         * This download is visible and shows in the notifications while
+         * in progress and after completion.
+         */
+        public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED = 1;
+
+        /**
+         * This download doesn't show in the UI or in the notifications.
+         */
+        public static final int VISIBILITY_HIDDEN = 2;
+
+        /** can take any of the following values: {@link #VISIBILITY_HIDDEN}
+         * {@link #VISIBILITY_VISIBLE_NOTIFY_COMPLETED}, {@link #VISIBILITY_VISIBLE}
+         */
+        private int mNotificationVisibility = VISIBILITY_VISIBLE;
+
+        /**
          * @param uri the HTTP URI to download.
          */
         public Request(Uri uri) {
@@ -475,9 +495,33 @@
          *
          * @param show whether the download manager should show a notification for this download.
          * @return this object
+         * @deprecated use {@link #setNotificationVisibility(int)}
          */
+        @Deprecated
         public Request setShowRunningNotification(boolean show) {
-            mShowNotification = show;
+            return (show) ? setNotificationVisibility(VISIBILITY_VISIBLE) :
+                    setNotificationVisibility(VISIBILITY_HIDDEN);
+        }
+
+        /**
+         * Control whether a system notification is posted by the download manager while this
+         * download is running or when it is completed.
+         * If enabled, the download manager posts notifications about downloads
+         * through the system {@link android.app.NotificationManager}.
+         * By default, a notification is shown only when the download is in progress.
+         *<p>
+         * It can take the following values: {@link #VISIBILITY_HIDDEN},
+         * {@link #VISIBILITY_VISIBLE},
+         * {@link #VISIBILITY_VISIBLE_NOTIFY_COMPLETED}.
+         *<p>
+         * If set to {@link #VISIBILITY_HIDDEN}, this requires the permission
+         * android.permission.DOWNLOAD_WITHOUT_NOTIFICATION.
+         *
+         * @param visibility the visibility setting value
+         * @return this object
+         */
+        public Request setNotificationVisibility(int visibility) {
+            mNotificationVisibility = visibility;
             return this;
         }
 
@@ -540,10 +584,7 @@
             putIfNonNull(values, Downloads.Impl.COLUMN_DESCRIPTION, mDescription);
             putIfNonNull(values, Downloads.Impl.COLUMN_MIME_TYPE, mMimeType);
 
-            values.put(Downloads.Impl.COLUMN_VISIBILITY,
-                    mShowNotification ? Downloads.Impl.VISIBILITY_VISIBLE
-                            : Downloads.Impl.VISIBILITY_HIDDEN);
-
+            values.put(Downloads.Impl.COLUMN_VISIBILITY, mNotificationVisibility);
             values.put(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, mAllowedNetworkTypes);
             values.put(Downloads.Impl.COLUMN_ALLOW_ROAMING, mRoamingAllowed);
             values.put(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI, mIsVisibleInDownloadsUi);
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 3ec0912..f27a15e 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -84,6 +84,10 @@
             return mInstance;
         }
         
+        if (mArguments != null) {
+            mArguments.setClassLoader(activity.getClassLoader());
+        }
+        
         mInstance = Fragment.instantiate(activity, mClassName, mArguments);
         
         if (mSavedFragmentState != null) {
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index d9a6171..45f9325 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1200,6 +1200,7 @@
                 f.mInLayout = false;
                 f.mAdded = false;
                 if (fs.mSavedFragmentState != null) {
+                    fs.mSavedFragmentState.setClassLoader(mActivity.getClassLoader());
                     f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
                             FragmentManagerImpl.VIEW_STATE_TAG);
                 }
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 0644f96..7f24d27 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -660,37 +660,40 @@
         final IntentReceiverLeaked mLocation;
         RuntimeException mUnregisterLocation;
 
-        final class Args implements Runnable {
+        final class Args extends BroadcastReceiver.PendingResult implements Runnable {
             private Intent mCurIntent;
-            private int mCurCode;
-            private String mCurData;
-            private Bundle mCurMap;
-            private boolean mCurOrdered;
-            private boolean mCurSticky;
+            private final boolean mOrdered;
 
+            public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
+                    boolean ordered, boolean sticky) {
+                super(resultCode, resultData, resultExtras,
+                        mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED,
+                        ordered, sticky, mIIntentReceiver.asBinder());
+                mCurIntent = intent;
+                mOrdered = ordered;
+            }
+            
             public void run() {
-                BroadcastReceiver receiver = mReceiver;
+                final BroadcastReceiver receiver = mReceiver;
+                final boolean ordered = mOrdered;
+                
                 if (ActivityThread.DEBUG_BROADCAST) {
                     int seq = mCurIntent.getIntExtra("seq", -1);
                     Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
                             + " seq=" + seq + " to " + mReceiver);
                     Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
-                            + " mCurOrdered=" + mCurOrdered);
+                            + " mOrderedHint=" + ordered);
                 }
                 
-                IActivityManager mgr = ActivityManagerNative.getDefault();
-                Intent intent = mCurIntent;
+                final IActivityManager mgr = ActivityManagerNative.getDefault();
+                final Intent intent = mCurIntent;
                 mCurIntent = null;
                 
                 if (receiver == null) {
-                    if (mRegistered && mCurOrdered) {
-                        try {
-                            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
-                                    "Finishing null broadcast to " + mReceiver);
-                            mgr.finishReceiver(mIIntentReceiver,
-                                    mCurCode, mCurData, mCurMap, false);
-                        } catch (RemoteException ex) {
-                        }
+                    if (mRegistered && ordered) {
+                        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
+                                "Finishing null broadcast to " + mReceiver);
+                        sendFinished(mgr);
                     }
                     return;
                 }
@@ -698,24 +701,14 @@
                 try {
                     ClassLoader cl =  mReceiver.getClass().getClassLoader();
                     intent.setExtrasClassLoader(cl);
-                    if (mCurMap != null) {
-                        mCurMap.setClassLoader(cl);
-                    }
-                    receiver.setOrderedHint(true);
-                    receiver.setResult(mCurCode, mCurData, mCurMap);
-                    receiver.clearAbortBroadcast();
-                    receiver.setOrderedHint(mCurOrdered);
-                    receiver.setInitialStickyHint(mCurSticky);
+                    setExtrasClassLoader(cl);
+                    receiver.setPendingResult(this);
                     receiver.onReceive(mContext, intent);
                 } catch (Exception e) {
-                    if (mRegistered && mCurOrdered) {
-                        try {
-                            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
-                                    "Finishing failed broadcast to " + mReceiver);
-                            mgr.finishReceiver(mIIntentReceiver,
-                                    mCurCode, mCurData, mCurMap, false);
-                        } catch (RemoteException ex) {
-                        }
+                    if (mRegistered && ordered) {
+                        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
+                                "Finishing failed broadcast to " + mReceiver);
+                        sendFinished(mgr);
                     }
                     if (mInstrumentation == null ||
                             !mInstrumentation.onException(mReceiver, e)) {
@@ -724,17 +717,9 @@
                             + " in " + mReceiver, e);
                     }
                 }
-                if (mRegistered && mCurOrdered) {
-                    try {
-                        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
-                                "Finishing broadcast to " + mReceiver);
-                        mgr.finishReceiver(mIIntentReceiver,
-                                receiver.getResultCode(),
-                                receiver.getResultData(),
-                                receiver.getResultExtras(false),
-                                receiver.getAbortBroadcast());
-                    } catch (RemoteException ex) {
-                    }
+                
+                if (receiver.getPendingResult() != null) {
+                    finish();
                 }
             }
         }
@@ -798,23 +783,13 @@
                 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
                         + " to " + mReceiver);
             }
-            Args args = new Args();
-            args.mCurIntent = intent;
-            args.mCurCode = resultCode;
-            args.mCurData = data;
-            args.mCurMap = extras;
-            args.mCurOrdered = ordered;
-            args.mCurSticky = sticky;
+            Args args = new Args(intent, resultCode, data, extras, ordered, sticky);
             if (!mActivityThread.post(args)) {
                 if (mRegistered && ordered) {
                     IActivityManager mgr = ActivityManagerNative.getDefault();
-                    try {
-                        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
-                                "Finishing sync broadcast to " + mReceiver);
-                        mgr.finishReceiver(mIIntentReceiver, args.mCurCode,
-                                args.mCurData, args.mCurMap, false);
-                    } catch (RemoteException ex) {
-                    }
+                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
+                            "Finishing sync broadcast to " + mReceiver);
+                    args.sendFinished(mgr);
                 }
             }
         }
diff --git a/core/java/android/app/QueuedWork.java b/core/java/android/app/QueuedWork.java
index af6bb1b..6ee4780 100644
--- a/core/java/android/app/QueuedWork.java
+++ b/core/java/android/app/QueuedWork.java
@@ -88,4 +88,14 @@
             toFinish.run();
         }
     }
+    
+    /**
+     * Returns true if there is pending work to be done.  Note that the
+     * result is out of data as soon as you receive it, so be careful how you
+     * use it.
+     */
+    public static boolean hasPendingWork() {
+        return !sPendingWorkFinishers.isEmpty();
+    }
+    
 }
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index c66b2de..556fb10 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -738,6 +738,27 @@
     }
 
     /**
+     * Get the current connection state of the local Bluetooth adapter.
+     * This can be used to check whether the local Bluetooth adapter is connected
+     * to any profile of any other remote Bluetooth Device.
+     *
+     * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
+     * intent to get the connection state of the adapter.
+     *
+     * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED},
+     * {@link #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
+     *
+     * @hide
+     */
+    public int getConnectionState() {
+        if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED;
+        try {
+            return mService.getAdapterConnectionState();
+        } catch (RemoteException e) {Log.e(TAG, "getConnectionState:", e);}
+        return BluetoothAdapter.STATE_DISCONNECTED;
+    }
+
+    /**
      * Picks RFCOMM channels until none are left.
      * Avoids reserved channels.
      */
@@ -879,6 +900,7 @@
         return socket;
     }
 
+
     /**
      * Construct an unencrypted, unauthenticated, RFCOMM server socket.
      * Call #accept to retrieve connections to this socket.
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index fd8f930..0c8e4d9 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -80,6 +80,7 @@
     public static final int UNPAIR = 100;
     public static final int AUTO_CONNECT_PROFILES = 101;
     public static final int TRANSITION_TO_STABLE = 102;
+    public static final int CONNECT_OTHER_PROFILES = 103;
 
     private static final int AUTO_CONNECT_DELAY = 6000; // 6 secs
 
@@ -149,10 +150,6 @@
                     sendMessage(TRANSITION_TO_STABLE);
                 }
             } else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
-                if (!getCurrentState().equals(mBondedDevice)) {
-                    Log.e(TAG, "State is: " + getCurrentState());
-                    return;
-                }
                 Message msg = new Message();
                 msg.what = AUTO_CONNECT_PROFILES;
                 sendMessageDelayed(msg, AUTO_CONNECT_DELAY);
@@ -330,6 +327,27 @@
                         }
                     }
                     break;
+                case CONNECT_OTHER_PROFILES:
+                    if (isPhoneDocked(mDevice)) {
+                       break;
+                    }
+                    if (message.arg1 == CONNECT_A2DP_OUTGOING) {
+                        if (mA2dpService != null &&
+                            mA2dpService.getConnectedDevices().size() == 0) {
+                            Log.i(TAG, "A2dp:Connect Other Profiles");
+                            mA2dpService.connect(mDevice);
+                        }
+                    } else if (message.arg1 == CONNECT_HFP_OUTGOING) {
+                        if (mHeadsetService == null) {
+                            deferMessage(message);
+                        } else {
+                            if (mHeadsetService.getConnectedDevices().size() == 0) {
+                                Log.i(TAG, "Headset:Connect Other Profiles");
+                                mHeadsetService.connect(mDevice);
+                            }
+                        }
+                    }
+                    break;
                 case TRANSITION_TO_STABLE:
                     // ignore.
                     break;
@@ -440,6 +458,7 @@
                 case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
+                case CONNECT_OTHER_PROFILES:
                     deferMessage(message);
                     break;
                 case TRANSITION_TO_STABLE:
@@ -519,6 +538,7 @@
                 case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
+                case CONNECT_OTHER_PROFILES:
                     deferMessage(message);
                     break;
                 case TRANSITION_TO_STABLE:
@@ -628,6 +648,7 @@
                 case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
+                case CONNECT_OTHER_PROFILES:
                     deferMessage(message);
                     break;
                 case TRANSITION_TO_STABLE:
@@ -705,6 +726,7 @@
                 case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
+                case CONNECT_OTHER_PROFILES:
                     deferMessage(message);
                     break;
                 case TRANSITION_TO_STABLE:
@@ -890,6 +912,7 @@
                 } else if (mHeadsetState == BluetoothHeadset.STATE_CONNECTING) {
                     return mHeadsetService.acceptIncomingConnect(mDevice);
                 } else if (mHeadsetState == BluetoothHeadset.STATE_DISCONNECTED) {
+                    handleConnectionOfOtherProfiles(command);
                     return mHeadsetService.createIncomingConnect(mDevice);
                 }
                 break;
@@ -899,6 +922,7 @@
                 }
                 break;
             case CONNECT_A2DP_INCOMING:
+                handleConnectionOfOtherProfiles(command);
                 // ignore, Bluez takes care
                 return true;
             case CONNECT_HID_OUTGOING:
@@ -960,6 +984,60 @@
         return false;
     }
 
+    private void handleConnectionOfOtherProfiles(int command) {
+        // The white paper recommendations mentions that when there is a
+        // link loss, it is the responsibility of the remote device to connect.
+        // Many connect only 1 profile - and they connect the second profile on
+        // some user action (like play being pressed) and so we need this code.
+        // Auto Connect code only connects to the last connected device - which
+        // is useful in cases like when the phone reboots. But consider the
+        // following case:
+        // User is connected to the car's phone and  A2DP profile.
+        // User comes to the desk  and places the phone in the dock
+        // (or any speaker or music system or even another headset) and thus
+        // gets connected to the A2DP profile.  User goes back to the car.
+        // Ideally the car's system is supposed to send incoming connections
+        // from both Handsfree and A2DP profile. But they don't. The Auto
+        // connect code, will not work here because we only auto connect to the
+        // last connected device for that profile which in this case is the dock.
+        // Now suppose a user is using 2 headsets simultaneously, one for the
+        // phone profile one for the A2DP profile. If this is the use case, we
+        // expect the user to use the preference to turn off the A2DP profile in
+        // the Settings screen for the first headset. Else, after link loss,
+        // there can be an incoming connection from the first headset which
+        // might result in the connection of the A2DP profile (if the second
+        // headset is slower) and thus the A2DP profile on the second headset
+        // will never get connected.
+        //
+        // TODO(): Handle other profiles here.
+        switch (command) {
+            case CONNECT_HFP_INCOMING:
+                // Connect A2DP if there is no incoming connection
+                // If the priority is OFF - don't auto connect.
+                // If the priority is AUTO_CONNECT, auto connect code takes care.
+                if (mA2dpService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON) {
+                    Message msg = new Message();
+                    msg.what = CONNECT_OTHER_PROFILES;
+                    msg.arg1 = CONNECT_A2DP_OUTGOING;
+                    sendMessageDelayed(msg, AUTO_CONNECT_DELAY);
+                }
+                break;
+            case CONNECT_A2DP_INCOMING:
+                // This is again against spec. HFP incoming connections should be made
+                // before A2DP, so we should not hit this case. But many devices
+                // don't follow this.
+                if (mHeadsetService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON) {
+                    Message msg = new Message();
+                    msg.what = CONNECT_OTHER_PROFILES;
+                    msg.arg1 = CONNECT_HFP_OUTGOING;
+                    sendMessageDelayed(msg, AUTO_CONNECT_DELAY);
+                }
+                break;
+            default:
+                break;
+        }
+
+    }
 
     /*package*/ BluetoothDevice getDevice() {
         return mDevice;
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 1eb269d..aefb3f2 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -47,6 +47,8 @@
     boolean isDiscovering();
     byte[] readOutOfBandData();
 
+    int getAdapterConnectionState();
+
     boolean createBond(in String address);
     boolean createBondOutOfBand(in String address, in byte[] hash, in byte[] randomizer);
     boolean cancelBondProcess(in String address);
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index b63d026..5939643 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -17,11 +17,14 @@
 package android.content;
 
 import android.app.ActivityManagerNative;
+import android.app.ActivityThread;
 import android.app.IActivityManager;
+import android.app.QueuedWork;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.Slog;
 
 /**
  * Base class for code that will receive intents sent by sendBroadcast().
@@ -160,6 +163,226 @@
  * the containing process active for the entire time of your operation.
  */
 public abstract class BroadcastReceiver {
+    private PendingResult mPendingResult;
+    private boolean mDebugUnregister;
+    
+    /**
+     * State for a result that is pending for a broadcast receiver.  Returned
+     * by {@link BroadcastReceiver#goAsync() goAsync()}
+     * while in {@link BroadcastReceiver#onReceive BroadcastReceiver.onReceive()}.
+     */
+    public static class PendingResult {
+        /** @hide */
+        public static final int TYPE_COMPONENT = 0;
+        /** @hide */
+        public static final int TYPE_REGISTERED = 1;
+        /** @hide */
+        public static final int TYPE_UNREGISTERED = 2;
+        
+        final int mType;
+        final boolean mOrderedHint;
+        final boolean mInitialStickyHint;
+        final IBinder mToken;
+        
+        int mResultCode;
+        String mResultData;
+        Bundle mResultExtras;
+        boolean mAbortBroadcast;
+        boolean mFinished;
+        
+        /** @hide */
+        public PendingResult(int resultCode, String resultData, Bundle resultExtras,
+                int type, boolean ordered, boolean sticky, IBinder token) {
+            mResultCode = resultCode;
+            mResultData = resultData;
+            mResultExtras = resultExtras;
+            mType = type;
+            mOrderedHint = ordered;
+            mInitialStickyHint = sticky;
+            mToken = token;
+        }
+        
+        /**
+         * Version of {@link BroadcastReceiver#setResultCode(int)
+         * BroadcastReceiver.setResultCode(int)} for
+         * asynchronous broadcast handling.
+         */
+        public final void setResultCode(int code) {
+            checkSynchronousHint();
+            mResultCode = code;
+        }
+
+        /**
+         * Version of {@link BroadcastReceiver#getResultCode()
+         * BroadcastReceiver.getResultCode()} for
+         * asynchronous broadcast handling.
+         */
+        public final int getResultCode() {
+            return mResultCode;
+        }
+
+        /**
+         * Version of {@link BroadcastReceiver#setResultData(String)
+         * BroadcastReceiver.setResultData(String)} for
+         * asynchronous broadcast handling.
+         */
+        public final void setResultData(String data) {
+            checkSynchronousHint();
+            mResultData = data;
+        }
+
+        /**
+         * Version of {@link BroadcastReceiver#getResultData()
+         * BroadcastReceiver.getResultData()} for
+         * asynchronous broadcast handling.
+         */
+        public final String getResultData() {
+            return mResultData;
+        }
+
+        /**
+         * Version of {@link BroadcastReceiver#setResultExtras(Bundle)
+         * BroadcastReceiver.setResultExtras(Bundle)} for
+         * asynchronous broadcast handling.
+         */
+        public final void setResultExtras(Bundle extras) {
+            checkSynchronousHint();
+            mResultExtras = extras;
+        }
+
+        /**
+         * Version of {@link BroadcastReceiver#getResultExtras(boolean)
+         * BroadcastReceiver.getResultExtras(boolean)} for
+         * asynchronous broadcast handling.
+         */
+        public final Bundle getResultExtras(boolean makeMap) {
+            Bundle e = mResultExtras;
+            if (!makeMap) return e;
+            if (e == null) mResultExtras = e = new Bundle();
+            return e;
+        }
+
+        /**
+         * Version of {@link BroadcastReceiver#setResult(int, String, Bundle)
+         * BroadcastReceiver.setResult(int, String, Bundle)} for
+         * asynchronous broadcast handling.
+         */
+        public final void setResult(int code, String data, Bundle extras) {
+            checkSynchronousHint();
+            mResultCode = code;
+            mResultData = data;
+            mResultExtras = extras;
+        }
+     
+        /**
+         * Version of {@link BroadcastReceiver#getAbortBroadcast()
+         * BroadcastReceiver.getAbortBroadcast()} for
+         * asynchronous broadcast handling.
+         */
+        public final boolean getAbortBroadcast() {
+            return mAbortBroadcast;
+        }
+
+        /**
+         * Version of {@link BroadcastReceiver#abortBroadcast()
+         * BroadcastReceiver.abortBroadcast()} for
+         * asynchronous broadcast handling.
+         */
+        public final void abortBroadcast() {
+            checkSynchronousHint();
+            mAbortBroadcast = true;
+        }
+        
+        /**
+         * Version of {@link BroadcastReceiver#clearAbortBroadcast()
+         * BroadcastReceiver.clearAbortBroadcast()} for
+         * asynchronous broadcast handling.
+         */
+        public final void clearAbortBroadcast() {
+            mAbortBroadcast = false;
+        }
+        
+        /**
+         * Finish the broadcast.  The current result will be sent and the
+         * next broadcast will proceed.
+         */
+        public final void finish() {
+            if (mType == TYPE_COMPONENT) {
+                final IActivityManager mgr = ActivityManagerNative.getDefault();
+                if (QueuedWork.hasPendingWork()) {
+                    // If this is a broadcast component, we need to make sure any
+                    // queued work is complete before telling AM we are done, so
+                    // we don't have our process killed before that.  We now know
+                    // there is pending work; put another piece of work at the end
+                    // of the list to finish the broadcast, so we don't block this
+                    // thread (which may be the main thread) to have it finished.
+                    //
+                    // Note that we don't need to use QueuedWork.add() with the
+                    // runnable, since we know the AM is waiting for us until the
+                    // executor gets to it.
+                    QueuedWork.singleThreadExecutor().execute( new Runnable() {
+                        @Override public void run() {
+                            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
+                                    "Finishing broadcast after work to component " + mToken);
+                            sendFinished(mgr);
+                        }
+                    });
+                } else {
+                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
+                            "Finishing broadcast to component " + mToken);
+                    sendFinished(mgr);
+                }
+            } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
+                if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
+                        "Finishing broadcast to " + mToken);
+                final IActivityManager mgr = ActivityManagerNative.getDefault();
+                sendFinished(mgr);
+            }
+        }
+        
+        /** @hide */
+        public void setExtrasClassLoader(ClassLoader cl) {
+            if (mResultExtras != null) {
+                mResultExtras.setClassLoader(cl);
+            }
+        }
+        
+        /** @hide */
+        public void sendFinished(IActivityManager am) {
+            synchronized (this) {
+                if (mFinished) {
+                    throw new IllegalStateException("Broadcast already finished");
+                }
+                mFinished = true;
+            
+                try {
+                    if (mOrderedHint) {
+                        am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
+                                mAbortBroadcast);
+                    } else {
+                        // This broadcast was sent to a component; it is not ordered,
+                        // but we still need to tell the activity manager we are done.
+                        am.finishReceiver(mToken, 0, null, null, false);
+                    }
+                } catch (RemoteException ex) {
+                }
+            }
+        }
+        
+        void checkSynchronousHint() {
+            // Note that we don't assert when receiving the initial sticky value,
+            // since that may have come from an ordered broadcast.  We'll catch
+            // them later when the real broadcast happens again.
+            if (mOrderedHint || mInitialStickyHint) {
+                return;
+            }
+            RuntimeException e = new RuntimeException(
+                    "BroadcastReceiver trying to return result during a non-ordered broadcast");
+            e.fillInStackTrace();
+            Log.e("BroadcastReceiver", e.getMessage(), e);
+        }
+    }
+    
     public BroadcastReceiver() {
     }
 
@@ -197,6 +420,26 @@
     public abstract void onReceive(Context context, Intent intent);
 
     /**
+     * This can be called by an application in {@link #onReceive} to allow
+     * it to keep the broadcast active after returning from that function.
+     * This does <em>not</em> change the expectation of being relatively
+     * responsive to the broadcast (finishing it within 10s), but does allow
+     * the implementation to move work related to it over to another thread
+     * to avoid glitching the main UI thread due to disk IO.
+     * 
+     * @return Returns a {@link PendingResult} representing the result of
+     * the active broadcast.  The BroadcastRecord itself is no longer active;
+     * all data and other interaction must go through {@link PendingResult}
+     * APIs.  The {@link PendingResult#finish PendingResult.finish()} method
+     * must be called once processing of the broadcast is done.
+     */
+    public final PendingResult goAsync() {
+        PendingResult res = mPendingResult;
+        mPendingResult = null;
+        return res;
+    }
+    
+    /**
      * Provide a binder to an already-running service.  This method is synchronous
      * and will not start the target service if it is not present, so it is safe
      * to call from {@link #onReceive}.
@@ -225,9 +468,9 @@
      * {@link android.app.Activity#RESULT_OK} constants, though the
      * actual meaning of this value is ultimately up to the broadcaster.
      * 
-     * <p><strong>This method does not work with non-ordered broadcasts such
+     * <p class="note">This method does not work with non-ordered broadcasts such
      * as those sent with {@link Context#sendBroadcast(Intent)
-     * Context.sendBroadcast}</strong></p>
+     * Context.sendBroadcast}</p>
      * 
      * @param code The new result code.
      * 
@@ -235,7 +478,7 @@
      */
     public final void setResultCode(int code) {
         checkSynchronousHint();
-        mResultCode = code;
+        mPendingResult.mResultCode = code;
     }
 
     /**
@@ -244,7 +487,7 @@
      * @return int The current result code.
      */
     public final int getResultCode() {
-        return mResultCode;
+        return mPendingResult != null ? mPendingResult.mResultCode : 0;
     }
 
     /**
@@ -264,7 +507,7 @@
      */
     public final void setResultData(String data) {
         checkSynchronousHint();
-        mResultData = data;
+        mPendingResult.mResultData = data;
     }
 
     /**
@@ -274,7 +517,7 @@
      * @return String The current result data; may be null.
      */
     public final String getResultData() {
-        return mResultData;
+        return mPendingResult != null ? mPendingResult.mResultData : null;
     }
 
     /**
@@ -296,7 +539,7 @@
      */
     public final void setResultExtras(Bundle extras) {
         checkSynchronousHint();
-        mResultExtras = extras;
+        mPendingResult.mResultExtras = extras;
     }
 
     /**
@@ -311,9 +554,12 @@
      * @return Map The current extras map.
      */
     public final Bundle getResultExtras(boolean makeMap) {
-        Bundle e = mResultExtras;
+        if (mPendingResult == null) {
+            return null;
+        }
+        Bundle e = mPendingResult.mResultExtras;
         if (!makeMap) return e;
-        if (e == null) mResultExtras = e = new Bundle();
+        if (e == null) mPendingResult.mResultExtras = e = new Bundle();
         return e;
     }
 
@@ -341,9 +587,9 @@
      */
     public final void setResult(int code, String data, Bundle extras) {
         checkSynchronousHint();
-        mResultCode = code;
-        mResultData = data;
-        mResultExtras = extras;
+        mPendingResult.mResultCode = code;
+        mPendingResult.mResultData = data;
+        mPendingResult.mResultExtras = extras;
     }
  
     /**
@@ -353,7 +599,7 @@
      * @return True if the broadcast should be aborted.
      */
     public final boolean getAbortBroadcast() {
-        return mAbortBroadcast;
+        return mPendingResult != null ? mPendingResult.mAbortBroadcast : false;
     }
 
     /**
@@ -372,7 +618,7 @@
      */
     public final void abortBroadcast() {
         checkSynchronousHint();
-        mAbortBroadcast = true;
+        mPendingResult.mAbortBroadcast = true;
     }
     
     /**
@@ -380,7 +626,9 @@
      * broadcast.
      */
     public final void clearAbortBroadcast() {
-        mAbortBroadcast = false;
+        if (mPendingResult != null) {
+            mPendingResult.mAbortBroadcast = false;
+        }
     }
     
     /**
@@ -388,7 +636,7 @@
      * broadcast.
      */
     public final boolean isOrderedBroadcast() {
-        return mOrderedHint;
+        return mPendingResult != null ? mPendingResult.mOrderedHint : false;
     }
     
     /**
@@ -398,7 +646,7 @@
      * not directly the result of a broadcast right now.
      */
     public final boolean isInitialStickyBroadcast() {
-        return mInitialStickyHint;
+        return mPendingResult != null ? mPendingResult.mInitialStickyHint : false;
     }
     
     /**
@@ -406,15 +654,21 @@
      * running in ordered mode.
      */
     public final void setOrderedHint(boolean isOrdered) {
-        mOrderedHint = isOrdered;
+        // Accidentally left in the SDK.
     }
     
     /**
-     * For internal use, sets the hint about whether this BroadcastReceiver is
-     * receiving the initial sticky broadcast value. @hide
+     * For internal use to set the result data that is active. @hide
      */
-    public final void setInitialStickyHint(boolean isInitialSticky) {
-        mInitialStickyHint = isInitialSticky;
+    public final void setPendingResult(PendingResult result) {
+        mPendingResult = result;
+    }
+    
+    /**
+     * For internal use to set the result data that is active. @hide
+     */
+    public final PendingResult getPendingResult() {
+        return mPendingResult;
     }
     
     /**
@@ -440,10 +694,14 @@
     }
     
     void checkSynchronousHint() {
+        if (mPendingResult == null) {
+            throw new IllegalStateException("Call while result is not pending");
+        }
+        
         // Note that we don't assert when receiving the initial sticky value,
         // since that may have come from an ordered broadcast.  We'll catch
         // them later when the real broadcast happens again.
-        if (mOrderedHint || mInitialStickyHint) {
+        if (mPendingResult.mOrderedHint || mPendingResult.mInitialStickyHint) {
             return;
         }
         RuntimeException e = new RuntimeException(
@@ -451,13 +709,5 @@
         e.fillInStackTrace();
         Log.e("BroadcastReceiver", e.getMessage(), e);
     }
-    
-    private int mResultCode;
-    private String mResultData;
-    private Bundle mResultExtras;
-    private boolean mAbortBroadcast;
-    private boolean mDebugUnregister;
-    private boolean mOrderedHint;
-    private boolean mInitialStickyHint;
 }
 
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index a19b132..6f4d098 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -37,8 +37,9 @@
  * each of which can hold one or more representations of an item of data.
  * For display to the user, it also has a label and iconic representation.</p>
  *
- * <p>A ClipData is a sub-class of {@link ClipDescription}, which describes
- * important meta-data about the clip.  In particular, its {@link #getMimeType(int)}
+ * <p>A ClipData contains a {@link ClipDescription}, which describes
+ * important meta-data about the clip.  In particular, its
+ * {@link ClipDescription#getMimeType(int) getDescription().getMimeType(int)}
  * must return correct MIME type(s) describing the data in the clip.  For help
  * in correctly constructing a clip with the correct MIME type, use
  * {@link #newPlainText(CharSequence, Bitmap, CharSequence)},
@@ -62,8 +63,8 @@
  * <p>If all you want is the textual representation of the clipped data, you
  * can use the convenience method {@link Item#coerceToText Item.coerceToText}.
  * In this case there is generally no need to worry about the MIME types
- * reported by {@link #getMimeType(int)}, since any clip item an always be
- * converted to a string.
+ * reported by {@link ClipDescription#getMimeType(int) getDescription().getMimeType(int)},
+ * since any clip item an always be converted to a string.
  *
  * <p>More complicated exchanges will be done through URIs, in particular
  * "content:" URIs.  A content URI allows the recipient of a ClippedData item
@@ -133,11 +134,16 @@
  * into an editor), then {@link Item#coerceToText(Context)} will ask the content
  * provider for the clip URI as text and successfully paste the entire note.
  */
-public class ClipData extends ClipDescription {
-    static final String[] MIMETYPES_TEXT_PLAIN = new String[] { MIMETYPE_TEXT_PLAIN };
-    static final String[] MIMETYPES_TEXT_URILIST = new String[] { MIMETYPE_TEXT_URILIST };
-    static final String[] MIMETYPES_TEXT_INTENT = new String[] { MIMETYPE_TEXT_INTENT };
+public class ClipData implements Parcelable {
+    static final String[] MIMETYPES_TEXT_PLAIN = new String[] {
+        ClipDescription.MIMETYPE_TEXT_PLAIN };
+    static final String[] MIMETYPES_TEXT_URILIST = new String[] {
+        ClipDescription.MIMETYPE_TEXT_URILIST };
+    static final String[] MIMETYPES_TEXT_INTENT = new String[] {
+        ClipDescription.MIMETYPE_TEXT_INTENT };
 
+    final ClipDescription mClipDescription;
+    
     final Bitmap mIcon;
 
     final ArrayList<Item> mItems = new ArrayList<Item>();
@@ -320,7 +326,7 @@
      * @param item The contents of the first item in the clip.
      */
     public ClipData(CharSequence label, String[] mimeTypes, Bitmap icon, Item item) {
-        super(label, mimeTypes);
+        mClipDescription = new ClipDescription(label, mimeTypes);
         if (item == null) {
             throw new NullPointerException("item is null");
         }
@@ -329,7 +335,25 @@
     }
 
     /**
-     * Create a new ClipData holding data of the type {@link #MIMETYPE_TEXT_PLAIN}.
+     * Create a new clip.
+     *
+     * @param description The ClipDescription describing the clip contents.
+     * @param icon Bitmap providing the user with an iconing representation of
+     * the clip.
+     * @param item The contents of the first item in the clip.
+     */
+    public ClipData(ClipDescription description, Bitmap icon, Item item) {
+        mClipDescription = description;
+        if (item == null) {
+            throw new NullPointerException("item is null");
+        }
+        mIcon = icon;
+        mItems.add(item);
+    }
+
+    /**
+     * Create a new ClipData holding data of the type
+     * {@link ClipDescription#MIMETYPE_TEXT_PLAIN}.
      *
      * @param label User-visible label for the clip data.
      * @param icon Iconic representation of the clip data.
@@ -342,7 +366,8 @@
     }
 
     /**
-     * Create a new ClipData holding an Intent with MIME type {@link #MIMETYPE_TEXT_INTENT}.
+     * Create a new ClipData holding an Intent with MIME type
+     * {@link ClipDescription#MIMETYPE_TEXT_INTENT}.
      *
      * @param label User-visible label for the clip data.
      * @param icon Iconic representation of the clip data.
@@ -358,7 +383,7 @@
      * Create a new ClipData holding a URI.  If the URI is a content: URI,
      * this will query the content provider for the MIME type of its data and
      * use that as the MIME type.  Otherwise, it will use the MIME type
-     * {@link #MIMETYPE_TEXT_URILIST}.
+     * {@link ClipDescription#MIMETYPE_TEXT_URILIST}.
      *
      * @param resolver ContentResolver used to get information about the URI.
      * @param label User-visible label for the clip data.
@@ -375,7 +400,7 @@
             mimeTypes = resolver.getStreamTypes(uri, "*/*");
             if (mimeTypes == null) {
                 if (realType != null) {
-                    mimeTypes = new String[] { realType, MIMETYPE_TEXT_URILIST };
+                    mimeTypes = new String[] { realType, ClipDescription.MIMETYPE_TEXT_URILIST };
                 }
             } else {
                 String[] tmp = new String[mimeTypes.length + (realType != null ? 2 : 1)];
@@ -385,7 +410,7 @@
                     i++;
                 }
                 System.arraycopy(mimeTypes, 0, tmp, i, mimeTypes.length);
-                tmp[i + mimeTypes.length] = MIMETYPE_TEXT_URILIST;
+                tmp[i + mimeTypes.length] = ClipDescription.MIMETYPE_TEXT_URILIST;
                 mimeTypes = tmp;
             }
         }
@@ -396,7 +421,8 @@
     }
 
     /**
-     * Create a new ClipData holding an URI with MIME type {@link #MIMETYPE_TEXT_URILIST}.
+     * Create a new ClipData holding an URI with MIME type
+     * {@link ClipDescription#MIMETYPE_TEXT_URILIST}.
      * Unlike {@link #newUri(ContentResolver, CharSequence, Bitmap, Uri)}, nothing
      * is inferred about the URI -- if it is a content: URI holding a bitmap,
      * the reported type will still be uri-list.  Use this with care!
@@ -411,6 +437,14 @@
         return new ClipData(label, MIMETYPES_TEXT_URILIST, icon, item);
     }
 
+    /**
+     * Return the {@link ClipDescription} associated with this data, describing
+     * what it contains.
+     */
+    public ClipDescription getDescription() {
+        return mClipDescription;
+    }
+    
     public void addItem(Item item) {
         if (item == null) {
             throw new NullPointerException("item is null");
@@ -437,7 +471,7 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
+        mClipDescription.writeToParcel(dest, flags);
         if (mIcon != null) {
             dest.writeInt(1);
             mIcon.writeToParcel(dest, flags);
@@ -465,7 +499,7 @@
     }
 
     ClipData(Parcel in) {
-        super(in);
+        mClipDescription = new ClipDescription(in);
         if (in.readInt() != 0) {
             mIcon = Bitmap.CREATOR.createFromParcel(in);
         } else {
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index c9115c5..34bd386 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -728,10 +728,16 @@
             newDelayInMs = maxSyncRetryTimeInSeconds * 1000;
         }
 
+        final long backoff = now + newDelayInMs;
+
         mSyncStorageEngine.setBackoff(op.account, op.authority,
-                now + newDelayInMs, newDelayInMs);
+                backoff, newDelayInMs);
+
+        op.backoff = backoff;
+        op.updateEffectiveRunTime();
+
         synchronized (mSyncQueue) {
-            mSyncQueue.onBackoffChanged(op.account, op.authority, now + newDelayInMs);
+            mSyncQueue.onBackoffChanged(op.account, op.authority, backoff);
         }
     }
 
diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java
index 96e6f22..93f9a71e 100644
--- a/core/java/android/database/sqlite/SQLiteClosable.java
+++ b/core/java/android/database/sqlite/SQLiteClosable.java
@@ -23,14 +23,12 @@
  */
 public abstract class SQLiteClosable {
     private int mReferenceCount = 1;
-    private Object mLock = new Object(); // STOPSHIP remove this line
 
     protected abstract void onAllReferencesReleased();
     protected void onAllReferencesReleasedFromContainer() {}
 
     public void acquireReference() {
-        synchronized(mLock) { // STOPSHIP change 'mLock' to 'this'
-            checkRefCount();
+        synchronized(this) {
             if (mReferenceCount <= 0) {
                 throw new IllegalStateException(
                         "attempt to re-open an already-closed object: " + getObjInfo());
@@ -40,8 +38,7 @@
     }
 
     public void releaseReference() {
-        synchronized(mLock) { // STOPSHIP change 'mLock' to 'this'
-            checkRefCount();
+        synchronized(this) {
             mReferenceCount--;
             if (mReferenceCount == 0) {
                 onAllReferencesReleased();
@@ -50,8 +47,7 @@
     }
 
     public void releaseReferenceFromContainer() {
-        synchronized(mLock) { // STOPSHIP change 'mLock' to 'this'
-            checkRefCount();
+        synchronized(this) {
             mReferenceCount--;
             if (mReferenceCount == 0) {
                 onAllReferencesReleasedFromContainer();
@@ -76,12 +72,4 @@
         buff.append(") ");
         return buff.toString();
     }
-
-    // STOPSHIP remove this method before shipping
-    private void checkRefCount() {
-        if (mReferenceCount > 1000) {
-            throw new IllegalStateException("bad refcount: " + mReferenceCount +
-                    ". file bug against frameworks->database" + getObjInfo());
-        }
-    }
 }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 6089013..c0743cfe 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1296,7 +1296,7 @@
             mInShowWindow = false;
         }
     }
-    
+
     void showWindowInner(boolean showInput) {
         boolean doShowInput = false;
         boolean wasVisible = mWindowVisible;
@@ -1311,7 +1311,7 @@
         } else {
             showInput = true;
         }
-        
+
         if (DEBUG) Log.v(TAG, "showWindow: updating UI");
         initialize();
         updateFullscreenMode();
@@ -1343,14 +1343,15 @@
         if (doShowInput) {
             startExtractingText(false);
         }
-        
+
         if (!wasVisible) {
             if (DEBUG) Log.v(TAG, "showWindow: showing!");
+            mImm.setIMEButtonVisible(mToken, true);
             onWindowShown();
             mWindow.show();
         }
     }
-    
+
     public void hideWindow() {
         if (mInputViewStarted) {
             if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
@@ -1364,11 +1365,12 @@
         if (mWindowVisible) {
             mWindow.hide();
             mWindowVisible = false;
+            mImm.setIMEButtonVisible(mToken, false);
             onWindowHidden();
             mWindowWasVisible = false;
         }
     }
-    
+
     /**
      * Called when the input method window has been shown to the user, after
      * previously not being visible.  This is done after all of the UI setup
diff --git a/core/java/android/nfc/FormatException.java b/core/java/android/nfc/FormatException.java
index 21a7c3b..7045a03 100644
--- a/core/java/android/nfc/FormatException.java
+++ b/core/java/android/nfc/FormatException.java
@@ -16,7 +16,6 @@
 
 package android.nfc;
 
-//TODO(npelly) javadoc or consider alternatives
 public class FormatException extends Exception {
     public FormatException() {
         super();
diff --git a/core/java/android/nfc/NdefMessage.java b/core/java/android/nfc/NdefMessage.java
index feca94e..d107b54 100644
--- a/core/java/android/nfc/NdefMessage.java
+++ b/core/java/android/nfc/NdefMessage.java
@@ -28,7 +28,7 @@
  * message always contains zero or more NDEF records.</p>
  * <p>This is an immutable data class.
  */
-public class NdefMessage implements Parcelable {
+public final class NdefMessage implements Parcelable {
     private static final byte FLAG_MB = (byte) 0x80;
     private static final byte FLAG_ME = (byte) 0x40;
 
@@ -69,9 +69,9 @@
      * Returns a byte array representation of this entire NDEF message.
      */
     public byte[] toByteArray() {
-        //TODO(nxp): do not return null
-        //TODO(nxp): allocate the byte array once, copy each record once
-        //TODO(nxp): process MB and ME flags outside loop
+        //TODO: do not return null
+        //TODO: allocate the byte array once, copy each record once
+        //TODO: process MB and ME flags outside loop
         if ((mRecords == null) || (mRecords.length == 0))
             return null;
 
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 557e44d..746d3df 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -35,7 +35,7 @@
  * large.
  * <p>This is an immutable data class.
  */
-public class NdefRecord implements Parcelable {
+public final class NdefRecord implements Parcelable {
     /**
      * Indicates no type, id, or payload is associated with this NDEF Record.
      * <p>
diff --git a/core/java/android/nfc/NdefTag.java b/core/java/android/nfc/NdefTag.java
index 0626edb..eb9d0dc 100644
--- a/core/java/android/nfc/NdefTag.java
+++ b/core/java/android/nfc/NdefTag.java
@@ -35,6 +35,7 @@
  * time and calls on this class will retrieve those read-only properties, and
  * not cause any further RF activity or block. Note however that arrays passed to and
  * returned by this class are *not* cloned, so be careful not to modify them.
+ * @hide
  */
 public class NdefTag extends Tag implements Parcelable {
     /**
diff --git a/core/java/android/nfc/NdefTagConnection.java b/core/java/android/nfc/NdefTagConnection.java
index 321b0ec..aafdbfd 100644
--- a/core/java/android/nfc/NdefTagConnection.java
+++ b/core/java/android/nfc/NdefTagConnection.java
@@ -28,6 +28,7 @@
  * <p class="note"><strong>Note:</strong>
  * Use of this class requires the {@link android.Manifest.permission#NFC}
  * permission.
+ * @hide
  */
 public class NdefTagConnection extends RawTagConnection {
     public static final int NDEF_MODE_READ_ONCE = 1;
@@ -42,8 +43,8 @@
      * Internal constructor, to be used by NfcAdapter
      * @hide
      */
-    /* package private */ NdefTagConnection(INfcAdapter service, NdefTag tag, String target) throws RemoteException {
-        super(service, tag);
+    /* package private */ NdefTagConnection(NfcAdapter adapter, NdefTag tag, String target) throws RemoteException {
+        super(adapter, tag);
         String[] targets = tag.getNdefTargets();
         int i;
 
@@ -63,8 +64,8 @@
      * Internal constructor, to be used by NfcAdapter
      * @hide
      */
-    /* package private */ NdefTagConnection(INfcAdapter service, NdefTag tag) throws RemoteException {
-        this(service, tag, tag.getNdefTargets()[0]);
+    /* package private */ NdefTagConnection(NfcAdapter adapter, NdefTag tag) throws RemoteException {
+        this(adapter, tag, tag.getNdefTargets()[0]);
     }
 
     /**
@@ -97,7 +98,7 @@
             msgArray[0] = msg;
             return msgArray;
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died");
+            attemptDeadServiceRecovery(e);
             return null;
         }
     }
@@ -134,7 +135,7 @@
                     throw new IOException();
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died");
+            attemptDeadServiceRecovery(e);
         }
     }
 
@@ -161,7 +162,7 @@
                     throw new IOException();
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died");
+            attemptDeadServiceRecovery(e);
             return false;
         }
     }
@@ -188,7 +189,7 @@
             return result;
 
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died");
+            attemptDeadServiceRecovery(e);
             return NDEF_MODE_UNKNOWN;
         }
     }
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 7f4b4a2..cf80faf 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -31,39 +31,31 @@
  * Use the static {@link #getDefaultAdapter} method to get the default NFC
  * Adapter for this Android device. Most Android devices will have only one NFC
  * Adapter, and {@link #getDefaultAdapter} returns the singleton object.
- * <p>
- * {@link NfcAdapter} can be used to create {@link RawTagConnection} or
- * {@link NdefTagConnection} connections to modify or perform low level access
- * to NFC Tags.
- * <p class="note">
- * <strong>Note:</strong> Some methods require the
- * {@link android.Manifest.permission#NFC} permission.
  */
 public final class NfcAdapter {
     /**
-     * Intent to start an activity when a non-NDEF tag is discovered.
-     * TODO(npelly) finalize decision on using CATEGORY or DATA URI to provide a
-     * hint for applications to filter the tag type.
-     * TODO(npelly) probably combine these two intents since tags aren't that simple
+     * Intent to start an activity when a tag is discovered.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
 
     /**
-     * Intent to start an activity when a NDEF tag is discovered. TODO(npelly)
-     * finalize decision on using CATEGORY or DATA URI to provide a hint for
-     * applications to filter the tag type.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_NDEF_TAG_DISCOVERED =
-            "android.nfc.action.NDEF_TAG_DISCOVERED";
-
-    /**
-     * Mandatory Tag extra for the ACTION_TAG and ACTION_NDEF_TAG intents.
+     * Mandatory Tag extra for the ACTION_TAG intents.
+     * @hide
      */
     public static final String EXTRA_TAG = "android.nfc.extra.TAG";
 
     /**
+     * Optional NdefMessage[] extra for the ACTION_TAG intents.
+     */
+    public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
+
+    /**
+     * Optional byte[] extra for the tag identifier.
+     */
+    public static final String EXTRA_ID = "android.nfc.extra.ID";
+
+    /**
      * Broadcast Action: a transaction with a secure element has been detected.
      * <p>
      * Always contains the extra field
@@ -168,7 +160,10 @@
     private static boolean sIsInitialized = false;
     private static NfcAdapter sAdapter;
 
-    private final INfcAdapter mService;
+    // Final after construction, except for attemptDeadServiceRecovery()
+    // when NFC crashes.
+    // Not locked - we accept a best effort attempt when NFC crashes.
+    /*package*/ INfcAdapter mService;
 
     private NfcAdapter(INfcAdapter service) {
         mService = service;
@@ -194,6 +189,16 @@
         }
     }
 
+    /** get handle to NFC service interface */
+    private static synchronized INfcAdapter getServiceInterface() {
+        /* get a handle to NFC service */
+        IBinder b = ServiceManager.getService("nfc");
+        if (b == null) {
+            return null;
+        }
+        return INfcAdapter.Stub.asInterface(b);
+    }
+
     /**
      * Get a handle to the default NFC Adapter on this Android device.
      * <p>
@@ -214,18 +219,31 @@
                 return null;
             }
 
-            /* get a handle to NFC service */
-            IBinder b = ServiceManager.getService("nfc");
-            if (b == null) {
+            INfcAdapter service = getServiceInterface();
+            if (service == null) {
                 Log.e(TAG, "could not retrieve NFC service");
                 return null;
             }
 
-            sAdapter = new NfcAdapter(INfcAdapter.Stub.asInterface(b));
+            sAdapter = new NfcAdapter(service);
             return sAdapter;
         }
     }
 
+    /** NFC service dead - attempt best effort recovery */
+    /*package*/ void attemptDeadServiceRecovery(Exception e) {
+        Log.e(TAG, "NFC service dead - attempting to recover", e);
+        INfcAdapter service = getServiceInterface();
+        if (service == null) {
+            Log.e(TAG, "could not retrieve NFC service during service recovery");
+            return;
+        }
+        /* assigning to mService is not thread-safe, but this is best-effort code
+         * and on a well-behaved system should never happen */
+        mService = service;
+        return;
+    }
+
     /**
      * Return true if this NFC Adapter has any features enabled.
      * <p>
@@ -241,7 +259,7 @@
         try {
             return mService.isEnabled();
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in isEnabled()", e);
+            attemptDeadServiceRecovery(e);
             return false;
         }
     }
@@ -258,7 +276,7 @@
         try {
             return mService.enable();
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in enable()", e);
+            attemptDeadServiceRecovery(e);
             return false;
         }
     }
@@ -277,7 +295,7 @@
         try {
             return mService.disable();
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in disable()", e);
+            attemptDeadServiceRecovery(e);
             return false;
         }
     }
@@ -298,12 +316,13 @@
      * <p>Requires {@link android.Manifest.permission#NFC} permission.
      *
      * @param message NDEF message to make public
+     * @hide
      */
     public void setLocalNdefMessage(NdefMessage message) {
         try {
             mService.localSet(message);
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died", e);
+            attemptDeadServiceRecovery(e);
         }
     }
 
@@ -312,12 +331,13 @@
      * <p>Requires {@link android.Manifest.permission#NFC} permission.
      *
      * @return NDEF Message that is publicly readable
+     * @hide
      */
     public NdefMessage getLocalNdefMessage() {
         try {
             return mService.localGet();
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died", e);
+            attemptDeadServiceRecovery(e);
             return null;
         }
     }
@@ -325,15 +345,16 @@
     /**
      * Create a raw tag connection to the default Target
      * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     * @hide
      */
     public RawTagConnection createRawTagConnection(Tag tag) {
         if (tag.mServiceHandle == 0) {
             throw new IllegalArgumentException("mock tag cannot be used for connections");
         }
         try {
-            return new RawTagConnection(mService, tag);
+            return new RawTagConnection(this, tag);
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died", e);
+            attemptDeadServiceRecovery(e);
             return null;
         }
     }
@@ -341,15 +362,16 @@
     /**
      * Create a raw tag connection to the specified Target
      * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     * @hide
      */
     public RawTagConnection createRawTagConnection(Tag tag, String target) {
         if (tag.mServiceHandle == 0) {
             throw new IllegalArgumentException("mock tag cannot be used for connections");
         }
         try {
-            return new RawTagConnection(mService, tag, target);
+            return new RawTagConnection(this, tag, target);
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died", e);
+            attemptDeadServiceRecovery(e);
             return null;
         }
     }
@@ -357,15 +379,16 @@
     /**
      * Create an NDEF tag connection to the default Target
      * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     * @hide
      */
     public NdefTagConnection createNdefTagConnection(NdefTag tag) {
         if (tag.mServiceHandle == 0) {
             throw new IllegalArgumentException("mock tag cannot be used for connections");
         }
         try {
-            return new NdefTagConnection(mService, tag);
+            return new NdefTagConnection(this, tag);
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died", e);
+            attemptDeadServiceRecovery(e);
             return null;
         }
     }
@@ -373,15 +396,16 @@
     /**
      * Create an NDEF tag connection to the specified Target
      * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     * @hide
      */
     public NdefTagConnection createNdefTagConnection(NdefTag tag, String target) {
         if (tag.mServiceHandle == 0) {
             throw new IllegalArgumentException("mock tag cannot be used for connections");
         }
         try {
-            return new NdefTagConnection(mService, tag, target);
+            return new NdefTagConnection(this, tag, target);
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died", e);
+            attemptDeadServiceRecovery(e);
             return null;
         }
     }
diff --git a/core/java/android/nfc/RawTagConnection.java b/core/java/android/nfc/RawTagConnection.java
index 8442893..bfdaa77 100644
--- a/core/java/android/nfc/RawTagConnection.java
+++ b/core/java/android/nfc/RawTagConnection.java
@@ -32,18 +32,24 @@
  * <p class="note"><strong>Note:</strong>
  * Use of this class requires the {@link android.Manifest.permission#NFC}
  * permission.
+ * @hide
  */
 public class RawTagConnection {
 
-    /*package*/ final INfcAdapter mService;
-    /*package*/ final INfcTag mTagService;
     /*package*/ final Tag mTag;
     /*package*/ boolean mIsConnected;
     /*package*/ String mSelectedTarget;
+    private final NfcAdapter mAdapter;
+
+    // Following fields are final after construction, except for
+    // during attemptDeadServiceRecovery() when NFC crashes.
+    // Not locked - we accept a best effort attempt when NFC crashes.
+    /*package*/ INfcAdapter mService;
+    /*package*/ INfcTag mTagService;
 
     private static final String TAG = "NFC";
 
-    /* package private */ RawTagConnection(INfcAdapter service, Tag tag, String target) throws RemoteException {
+    /*package*/ RawTagConnection(NfcAdapter adapter, Tag tag, String target) throws RemoteException {
         String[] targets = tag.getRawTargets();
         int i;
 
@@ -58,14 +64,28 @@
             throw new IllegalArgumentException();
         }
 
-        mService = service;
-        mTagService = service.getNfcTagInterface();
+        mAdapter = adapter;
+        mService = mAdapter.mService;
+        mTagService = mService.getNfcTagInterface();
         mTag = tag;
         mSelectedTarget = target;
     }
 
-    /* package private */ RawTagConnection(INfcAdapter service, Tag tag) throws RemoteException {
-        this(service, tag, tag.getRawTargets()[0]);
+    /*package*/ RawTagConnection(NfcAdapter adapter, Tag tag) throws RemoteException {
+        this(adapter, tag, tag.getRawTargets()[0]);
+    }
+
+    /** NFC service dead - attempt best effort recovery */
+    /*package*/ void attemptDeadServiceRecovery(Exception e) {
+        mAdapter.attemptDeadServiceRecovery(e);
+        /* assigning to mService is not thread-safe, but this is best-effort code
+         * and on a well-behaved system should never happen */
+        mService = mAdapter.mService;
+        try {
+            mTagService = mService.getNfcTagInterface();
+        } catch (RemoteException e2) {
+            Log.e(TAG, "second RemoteException trying to recover from dead NFC service", e2);
+        }
     }
 
     /**
@@ -101,7 +121,7 @@
         try {
             return mTagService.isPresent(mTag.mServiceHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died", e);
+            attemptDeadServiceRecovery(e);
             return false;
         }
     }
@@ -136,7 +156,7 @@
         try {
             mTagService.close(mTag.mServiceHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died", e);
+            attemptDeadServiceRecovery(e);
         }
     }
 
@@ -159,7 +179,7 @@
             }
             return response;
         } catch (RemoteException e) {
-            Log.e(TAG, "NFC service died", e);
+            attemptDeadServiceRecovery(e);
             throw new IOException("NFC service died");
         }
     }
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index dc6e798..5d0b04c 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -41,6 +41,7 @@
  * time and calls on this class will retrieve those read-only properties, and
  * not cause any further RF activity or block. Note however that arrays passed to and
  * returned by this class are *not* cloned, so be careful not to modify them.
+ * @hide
  */
 public class Tag implements Parcelable {
     /**
@@ -156,6 +157,7 @@
      * from SENSF_RES
      *
      * @return poll bytes, or null if they do not exist for this Tag technology
+     * @hide
      */
     public byte[] getPollBytes() {
         return mPollBytes;
@@ -172,6 +174,7 @@
      * <p>JIS_X_6319_4: null
      * <p>ISO15693: response flags (1 byte), DSFID (1 byte): null
      * @return activation bytes, or null if they do not exist for this Tag technology
+     * @hide
      */
     public byte[] getActivationBytes() {
         return mActivationBytes;
diff --git a/core/java/android/nfc/package.html b/core/java/android/nfc/package.html
index 8754cb9..b054d1c 100644
--- a/core/java/android/nfc/package.html
+++ b/core/java/android/nfc/package.html
@@ -1,30 +1,18 @@
 <HTML>
 <BODY>
-Provides access to Near Field Communication (NFC) functionality, allowing applications to connect
-to NFC tags, then transmit and recieving data. A "tag" may actually be another device that appears
-as a tag.
+Provides access to Near Field Communication (NFC) functionality, allowing applications to read
+NDEF message in NFC tags. A "tag" may actually be another device that appears as a tag.
 
 <p>Here's a summary of the classes:</p>
 
 <dl>
   <dt>{@link android.nfc.NfcAdapter}</dt>
   <dd>This represents the device's NFC adapter, which is your entry-point to performing NFC
-operations. Once you acquire an instance with {@link android.nfc.NfcAdapter#getDefaultAdapter}, you
-can create connections to tags.</dd>
-  <dt>{@link android.nfc.NdefTag} and {@link android.nfc.Tag}</dt>
-  <dd>These objects represent a tag. A tag is a thing that the NFC-enabled device can
-communicate with when within range. Usually, you'll work with {@link android.nfc.NdefTag}, which
-represents a tag that's compliant with the NFC Data Exchange Format (NDEF); a {@link
-android.nfc.Tag} represents a generalized tag. Note that {@link android.nfc.NdefTag} extends
-{@link android.nfc.Tag}.</dd>
-  <dt>{@link android.nfc.NdefTagConnection} and {@link android.nfc.RawTagConnection}</dt>
-  <dd>These objects represent a connection to a tag, respective to the type of tag connected
-(either {@link android.nfc.NdefTag} or {@link android.nfc.Tag}). Note that {@link
-android.nfc.NdefTagConnection} extends {@link android.nfc.RawTagConnection}.</dd>
+operations. You can acquire an instance with {@link android.nfc.NfcAdapter#getDefaultAdapter}.</dd>
   <dt>{@link android.nfc.NdefMessage}</dt>
   <dd>Represents an NDEF data message, which is the standard format in which "records"
 carrying data are transmitted between devices and tags. Your application can receive these
-messages from an {@link android.nfc.NdefTagConnection}.</dd>
+messages from an {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED} intent.</dd>
   <dt>{@link android.nfc.NdefRecord}</dt>
   <dd>Represents a record, which is delivered in a {@link android.nfc.NdefMessage} and describes the
 type of data being shared and carries the data itself.</dd>
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 247b281..c62715b 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -87,7 +87,7 @@
 
     /**
      * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
-     * Boolean value set to true if an unsupported charger is attached
+     * Int value set to nonzero if an unsupported charger is attached
      * to the device.
      * {@hide}
      */
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 0ec1c74..8eac7aa 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -181,6 +181,13 @@
     }
 
     /**
+     * Return the ClassLoader currently associated with this Bundle.
+     */
+    public ClassLoader getClassLoader() {
+        return mClassLoader;
+    }
+    
+    /**
      * Clones the current Bundle. The internal map is cloned, but the keys and
      * values to which it refers are copied by reference.
      */
diff --git a/core/java/android/os/NetworkOnMainThreadException.java b/core/java/android/os/NetworkOnMainThreadException.java
new file mode 100644
index 0000000..dd8c66c
--- /dev/null
+++ b/core/java/android/os/NetworkOnMainThreadException.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+/**
+ * The exception that is thrown when an application attempts
+ * to perform a networking operation on its main thread.
+ *
+ * <p>This is only thrown for applications targeting the Honeycomb
+ * SDK or higher.  Applications targeting earlier SDK versions
+ * are allowed to do networking on their main event loop threads,
+ * but it's heavily discouraged.  See the document
+ * <a href="{@docRoot}guide/practices/design/responsiveness.html">
+ * Designing for Responsiveness</a>.
+ *
+ * <p>Also see {@link StrictMode}.
+ */
+public class NetworkOnMainThreadException extends RuntimeException {
+}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 9786959..5a6369c 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -150,11 +150,20 @@
     public static final int PENALTY_DIALOG = 0x20;
 
     /**
+     * Death on any detected violation.
+     *
      * @hide
      */
     public static final int PENALTY_DEATH = 0x40;
 
     /**
+     * Death just for detected network usage.
+     *
+     * @hide
+     */
+    public static final int PENALTY_DEATH_ON_NETWORK = 0x200;
+
+    /**
      * @hide
      */
     public static final int PENALTY_DROPBOX = 0x80;
@@ -173,6 +182,13 @@
     public static final int PENALTY_GATHER = 0x100;
 
     /**
+     * Mask of all the penalty bits.
+     */
+    private static final int PENALTY_MASK =
+            PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
+            PENALTY_DEATH_ON_NETWORK;
+
+    /**
      * The current VmPolicy in effect.
      */
     private static volatile int sVmPolicyMask = 0;
@@ -317,12 +333,28 @@
              * Crash the whole process on violation.  This penalty runs at
              * the end of all enabled penalties so you'll still get
              * see logging or other violations before the process dies.
+             *
+             * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies
+             * to disk reads, disk writes, and network usage if their
+             * corresponding detect flags are set.
              */
             public Builder penaltyDeath() {
                 return enable(PENALTY_DEATH);
             }
 
             /**
+             * Crash the whole process on any network usage.  Unlike
+             * {@link #penaltyDeath}, this penalty runs
+             * <em>before</em> anything else.  You must still have
+             * called {@link #detectNetwork} to enable this.
+             *
+             * <p>In the Honeycomb or later SDKs, this is on by default.
+             */
+            public Builder penaltyDeathOnNetwork() {
+                return enable(PENALTY_DEATH_ON_NETWORK);
+            }
+
+            /**
              * Log detected violations to the system log.
              */
             public Builder penaltyLog() {
@@ -643,6 +675,18 @@
     }
 
     /**
+     * Used by the framework to make network usage on the main
+     * thread a fatal error.
+     *
+     * @hide
+     */
+    public static void enableDeathOnNetwork() {
+        int oldPolicy = getThreadPolicyMask();
+        int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
+        setThreadPolicyMask(newPolicy);
+    }
+
+    /**
      * Parses the BlockGuard policy mask out from the Exception's
      * getMessage() String value.  Kinda gross, but least
      * invasive.  :/
@@ -752,6 +796,9 @@
             if ((mPolicyMask & DETECT_NETWORK) == 0) {
                 return;
             }
+            if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
+                throw new NetworkOnMainThreadException();
+            }
             if (tooManyViolationsThisLoop()) {
                 return;
             }
@@ -882,7 +929,7 @@
                 }
             }
 
-            // The violationMask, passed to ActivityManager, is a
+            // The violationMaskSubset, passed to ActivityManager, is a
             // subset of the original StrictMode policy bitmask, with
             // only the bit violated and penalty bits to be executed
             // by the ActivityManagerService remaining set.
@@ -900,7 +947,35 @@
             if (violationMaskSubset != 0) {
                 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
                 violationMaskSubset |= violationBit;
+                final int violationMaskSubsetFinal = violationMaskSubset;
                 final int savedPolicyMask = getThreadPolicyMask();
+
+                final boolean justDropBox = (info.policy & PENALTY_MASK) == PENALTY_DROPBOX;
+                if (justDropBox) {
+                    // If all we're going to ask the activity manager
+                    // to do is dropbox it (the common case during
+                    // platform development), we can avoid doing this
+                    // call synchronously which Binder data suggests
+                    // isn't always super fast, despite the implementation
+                    // in the ActivityManager trying to be mostly async.
+                    new Thread("callActivityManagerForStrictModeDropbox") {
+                        public void run() {
+                            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+                            try {
+                                ActivityManagerNative.getDefault().
+                                        handleApplicationStrictModeViolation(
+                                            RuntimeInit.getApplicationObject(),
+                                            violationMaskSubsetFinal,
+                                            info);
+                            } catch (RemoteException e) {
+                                Log.e(TAG, "RemoteException handling StrictMode violation", e);
+                            }
+                        }
+                    }.start();
+                    return;
+                }
+
+                // Normal synchronous call to the ActivityManager.
                 try {
                     // First, remove any policy before we call into the Activity Manager,
                     // otherwise we'll infinite recurse as we try to log policy violations
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index a59b2f8..0c6a237 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -893,13 +893,13 @@
         }
     }
 
-    public void switchToHeaderInner(String fragmentName, Bundle args, boolean next) {
+    private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {
         getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
         Fragment f = Fragment.instantiate(this, fragmentName, args);
         FragmentTransaction transaction = getFragmentManager().openTransaction();
-        transaction.setTransition(next ?
-                FragmentTransaction.TRANSIT_FRAGMENT_NEXT :
-                FragmentTransaction.TRANSIT_FRAGMENT_PREV);
+        transaction.setTransition(direction == 0 ? FragmentTransaction.TRANSIT_NONE
+                : direction > 0 ? FragmentTransaction.TRANSIT_FRAGMENT_NEXT
+                        : FragmentTransaction.TRANSIT_FRAGMENT_PREV);
         transaction.replace(com.android.internal.R.id.prefs, f);
         transaction.commit();
     }
@@ -913,7 +913,7 @@
      */
     public void switchToHeader(String fragmentName, Bundle args) {
         setSelectedHeader(null);
-        switchToHeaderInner(fragmentName, args, true);
+        switchToHeaderInner(fragmentName, args, 0);
     }
 
     /**
@@ -923,8 +923,8 @@
      * @param header The new header to display.
      */
     public void switchToHeader(Header header) {
-        switchToHeaderInner(header.fragment, header.fragmentArguments,
-                mHeaders.indexOf(header) > mHeaders.indexOf(mCurHeader));
+        int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader);
+        switchToHeaderInner(header.fragment, header.fragmentArguments, direction);
         setSelectedHeader(header);
     }
 
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index 7629c31..33f37f8 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -151,7 +151,7 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        return inflater.inflate(com.android.internal.R.layout.preference_list_content,
+        return inflater.inflate(com.android.internal.R.layout.preference_list_fragment,
                 container, false);
     }
 
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 0448ec0..9e6434a 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -5127,6 +5127,47 @@
              * <P>Type: TEXT</P>
              */
             public static final String NAME = DATA;
+
+            /**
+             * Return the string resource that best describes the given
+             * {@link #TYPE}. Will always return a valid resource.
+             */
+            public static final int getTypeLabelResource(int type) {
+                switch (type) {
+                    case TYPE_ASSISTANT: return com.android.internal.R.string.relationTypeAssistant;
+                    case TYPE_BROTHER: return com.android.internal.R.string.relationTypeBrother;
+                    case TYPE_CHILD: return com.android.internal.R.string.relationTypeChild;
+                    case TYPE_DOMESTIC_PARTNER:
+                            return com.android.internal.R.string.relationTypeDomesticPartner;
+                    case TYPE_FATHER: return com.android.internal.R.string.relationTypeFather;
+                    case TYPE_FRIEND: return com.android.internal.R.string.relationTypeFriend;
+                    case TYPE_MANAGER: return com.android.internal.R.string.relationTypeManager;
+                    case TYPE_MOTHER: return com.android.internal.R.string.relationTypeMother;
+                    case TYPE_PARENT: return com.android.internal.R.string.relationTypeParent;
+                    case TYPE_PARTNER: return com.android.internal.R.string.relationTypePartner;
+                    case TYPE_REFERRED_BY:
+                            return com.android.internal.R.string.relationTypeReferredBy;
+                    case TYPE_RELATIVE: return com.android.internal.R.string.relationTypeRelative;
+                    case TYPE_SISTER: return com.android.internal.R.string.relationTypeSister;
+                    case TYPE_SPOUSE: return com.android.internal.R.string.relationTypeSpouse;
+                    default: return com.android.internal.R.string.orgTypeCustom;
+                }
+            }
+
+            /**
+             * Return a {@link CharSequence} that best describes the given type,
+             * possibly substituting the given {@link #LABEL} value
+             * for {@link #TYPE_CUSTOM}.
+             */
+            public static final CharSequence getTypeLabel(Resources res, int type,
+                    CharSequence label) {
+                if (type == TYPE_CUSTOM && !TextUtils.isEmpty(label)) {
+                    return label;
+                } else {
+                    final int labelRes = getTypeLabelResource(type);
+                    return res.getText(labelRes);
+                }
+            }
         }
 
         /**
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index c9e3b69..7054888 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -16,6 +16,7 @@
 
 package android.provider;
 
+import android.app.DownloadManager;
 import android.net.Uri;
 
 /**
@@ -621,18 +622,19 @@
          * This download is visible but only shows in the notifications
          * while it's in progress.
          */
-        public static final int VISIBILITY_VISIBLE = 0;
+        public static final int VISIBILITY_VISIBLE = DownloadManager.Request.VISIBILITY_VISIBLE;
 
         /**
          * This download is visible and shows in the notifications while
          * in progress and after completion.
          */
-        public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED = 1;
+        public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED =
+                DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED;
 
         /**
          * This download doesn't show in the UI or in the notifications.
          */
-        public static final int VISIBILITY_HIDDEN = 2;
+        public static final int VISIBILITY_HIDDEN = DownloadManager.Request.VISIBILITY_HIDDEN;
 
         /**
          * Constants related to HTTP request headers associated with each download.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 62d2ff2..ee53828 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -279,6 +279,20 @@
             "android.settings.INPUT_METHOD_SETTINGS";
 
     /**
+     * Activity Action: Show enabler activity to enable/disable input methods and subtypes.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_INPUT_METHOD_AND_SUBTYPE_ENABLER =
+            "android.settings.INPUT_METHOD_AND_SUBTYPE_ENABLER";
+
+    /**
      * Activity Action: Show settings to manage the user input dictionary.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
@@ -1627,11 +1641,10 @@
         public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
 
         /**
-         * Whether live web suggestions while the user types into search dialogs are
-         * enabled. Browsers and other search UIs should respect this, as it allows
-         * a user to avoid sending partial queries to a search engine, if it poses
-         * any privacy concern. The value is boolean (1 or 0).
+         * @deprecated Each application that shows web suggestions should have its own
+         * setting for this.
          */
+        @Deprecated
         public static final String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
 
         /**
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 65047c0..7289012 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -167,6 +167,8 @@
     private static String mDockAddress;
     private String mDockPin;
 
+    private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
+
     private static class RemoteService {
         public String address;
         public ParcelUuid uuid;
@@ -415,6 +417,7 @@
         mProfilesConnected = 0;
         mProfilesConnecting = 0;
         mProfilesDisconnecting = 0;
+        mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
 
         if (saveSetting) {
             persistBluetoothOnSetting(false);
@@ -2737,11 +2740,18 @@
         }
     }
 
+    public int getAdapterConnectionState() {
+        return mAdapterConnectionState;
+    }
+
     public synchronized void sendConnectionStateChange(BluetoothDevice device, int state,
                                                         int prevState) {
         if (updateCountersAndCheckForConnectionStateChange(device, state, prevState)) {
-            state = getAdapterConnectionState(state);
-            prevState = getAdapterConnectionState(prevState);
+            state = translateToAdapterConnectionState(state);
+            prevState = translateToAdapterConnectionState(prevState);
+
+            mAdapterConnectionState = state;
+
             Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
             intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
             intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, state);
@@ -2751,7 +2761,7 @@
         }
     }
 
-    private int getAdapterConnectionState(int state) {
+    private int translateToAdapterConnectionState(int state) {
         switch (state) {
             case BluetoothProfile.STATE_CONNECTING:
                 return BluetoothAdapter.STATE_CONNECTING;
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 9645a17..26346d2 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -655,7 +655,10 @@
             if (!mDestroyed) {
                 if (DEBUG) Log.v(TAG, "onDesiredSizeChanged("
                         + desiredWidth + "," + desiredHeight + "): " + this);
+                mIWallpaperEngine.mReqWidth = desiredWidth;
+                mIWallpaperEngine.mReqHeight = desiredHeight;
                 onDesiredSizeChanged(desiredWidth, desiredHeight);
+                doOffsetsChanged();
             }
         }
         
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 8e355d6..033ee7c 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -33,6 +33,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewRoot;
+import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.view.IInputConnectionWrapper;
@@ -518,6 +519,15 @@
     }
 
     /** @hide */
+    public void setIMEButtonVisible(IBinder imeToken, boolean visible) {
+        try {
+            mService.setIMEButtonVisible(imeToken, visible);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /** @hide */
     public void setFullscreenMode(boolean fullScreen) {
         mFullscreenMode = fullScreen;
     }
@@ -1411,6 +1421,17 @@
         }
     }
 
+    public InputMethodSubtype getCurrentInputMethodSubtype() {
+        synchronized (mH) {
+            try {
+                return mService.getCurrentInputMethodSubtype();
+            } catch (RemoteException e) {
+                Log.w(TAG, "IME died: " + mCurId, e);
+                return null;
+            }
+        }
+    }
+
     void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
         final Printer p = new PrintWriterPrinter(fout);
         p.println("Input method client state for " + this + ":");
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 6e588b9..2087664 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -74,8 +74,6 @@
     // queue has been cleared,they are ignored.
     private boolean mBlockMessages = false;
     private int mOrientation = -1;
-    private static String sDatabaseDirectory;
-    private static String sCacheDirectory;
 
     // Is this frame the main frame?
     private boolean mIsMainFrame;
@@ -229,13 +227,6 @@
         AssetManager am = context.getAssets();
         nativeCreateFrame(w, am, proxy.getBackForwardList());
 
-        if (sDatabaseDirectory == null) {
-            sDatabaseDirectory = appContext.getDatabasePath("dummy").getParent();
-        }
-        if (sCacheDirectory == null) {
-            sCacheDirectory = appContext.getCacheDir().getAbsolutePath();
-        }
-
         if (DebugFlags.BROWSER_FRAME) {
             Log.v(LOGTAG, "BrowserFrame constructor: this=" + this);
         }
@@ -658,22 +649,6 @@
     }
 
     /**
-     * Called by JNI. Gets the application's database directory, excluding the trailing slash.
-     * @return String The application's database directory
-     */
-    private static String getDatabaseDirectory() {
-        return sDatabaseDirectory;
-    }
-
-    /**
-     * Called by JNI. Gets the application's cache directory, excluding the trailing slash.
-     * @return String The application's cache directory
-     */
-    private static String getCacheDirectory() {
-        return sCacheDirectory;
-    }
-
-    /**
      * Called by JNI.
      * Read from an InputStream into a supplied byte[]
      * This method catches any exceptions so they don't crash the JVM.
@@ -752,6 +727,14 @@
             }
         } else if (type == CONTENT) {
             try {
+                // Strip off mimetype, for compatibility with ContentLoader.java
+                // If we don't do this, we can fail to load Gmail attachments,
+                // because the URL being loaded doesn't exactly match the URL we
+                // have permission to read.
+                int mimeIndex = url.lastIndexOf('?');
+                if (mimeIndex != -1) {
+                    url = url.substring(0, mimeIndex);
+                }
                 Uri uri = Uri.parse(url);
                 return mContext.getContentResolver().openInputStream(uri);
             } catch (Exception e) {
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 3010178..8691714 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -273,6 +273,11 @@
      * @param accept TRUE if accept cookie
      */
     public synchronized void setAcceptCookie(boolean accept) {
+        if (useChromiumHttpStack()) {
+            nativeSetAcceptCookie(accept);
+            return;
+        }
+
         mAcceptCookie = accept;
     }
 
@@ -281,6 +286,10 @@
      * @return TRUE if accept cookie
      */
     public synchronized boolean acceptCookie() {
+        if (useChromiumHttpStack()) {
+            return nativeAcceptCookie();
+        }
+
         return mAcceptCookie;
     }
 
@@ -292,6 +301,11 @@
      * @param value The value for set-cookie: in http response header
      */
     public void setCookie(String url, String value) {
+        if (useChromiumHttpStack()) {
+            nativeSetCookie(url, value);
+            return;
+        }
+
         WebAddress uri;
         try {
             uri = new WebAddress(url);
@@ -418,6 +432,10 @@
      * @return The cookies in the format of NAME=VALUE [; NAME=VALUE]
      */
     public String getCookie(String url) {
+        if (useChromiumHttpStack()) {
+            return nativeGetCookie(url);
+        }
+
         WebAddress uri;
         try {
             uri = new WebAddress(url);
@@ -509,6 +527,11 @@
      * Remove all session cookies, which are cookies without expiration date
      */
     public void removeSessionCookie() {
+        if (useChromiumHttpStack()) {
+            nativeRemoveSessionCookie();
+            return;
+        }
+
         final Runnable clearCache = new Runnable() {
             public void run() {
                 synchronized(CookieManager.this) {
@@ -556,6 +579,10 @@
      *  Return true if there are stored cookies.
      */
     public synchronized boolean hasCookies() {
+        if (useChromiumHttpStack()) {
+            return nativeHasCookies();
+        }
+
         return CookieSyncManager.getInstance().hasCookies();
     }
 
@@ -563,6 +590,11 @@
      * Remove all expired cookies
      */
     public void removeExpiredCookie() {
+        if (useChromiumHttpStack()) {
+            nativeRemoveExpiredCookie();
+            return;
+        }
+
         final Runnable clearCache = new Runnable() {
             public void run() {
                 synchronized(CookieManager.this) {
@@ -1035,5 +1067,12 @@
 
     // Native functions
     private static native boolean nativeUseChromiumHttpStack();
+    private static native boolean nativeAcceptCookie();
+    private static native String nativeGetCookie(String url);
+    private static native boolean nativeHasCookies();
     private static native void nativeRemoveAllCookie();
+    private static native void nativeRemoveExpiredCookie();
+    private static native void nativeRemoveSessionCookie();
+    private static native void nativeSetAcceptCookie(boolean accept);
+    private static native void nativeSetCookie(String url, String value);
 }
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
index abe9178..8b76a3b 100644
--- a/core/java/android/webkit/CookieSyncManager.java
+++ b/core/java/android/webkit/CookieSyncManager.java
@@ -65,6 +65,11 @@
     // time when last update happened
     private long mLastUpdate;
 
+    // Used by the Chromium HTTP stack. Everything else in this class is used only by the Android
+    // Java HTTP stack.
+    private static String sDatabaseDirectory;
+    private static String sCacheDirectory;
+
     private CookieSyncManager(Context context) {
         super(context, "CookieSyncManager");
     }
@@ -77,11 +82,7 @@
      * @return CookieSyncManager
      */
     public static synchronized CookieSyncManager getInstance() {
-        if (sRef == null) {
-            throw new IllegalStateException(
-                    "CookieSyncManager::createInstance() needs to be called "
-                            + "before CookieSyncManager::getInstance()");
-        }
+        checkInstanceIsCreated();
         return sRef;
     }
 
@@ -92,8 +93,11 @@
      */
     public static synchronized CookieSyncManager createInstance(
             Context context) {
+        Context appContext = context.getApplicationContext();
         if (sRef == null) {
-            sRef = new CookieSyncManager(context.getApplicationContext());
+            sRef = new CookieSyncManager(appContext);
+            sDatabaseDirectory = appContext.getDatabasePath("dummy").getParent();
+            sCacheDirectory = appContext.getCacheDir().getAbsolutePath();
         }
         return sRef;
     }
@@ -210,4 +214,30 @@
             }
         }
     }
+
+    private static void checkInstanceIsCreated() {
+        if (sRef == null) {
+            throw new IllegalStateException(
+                    "CookieSyncManager::createInstance() needs to be called "
+                            + "before CookieSyncManager::getInstance()");
+        }
+    }
+
+    /**
+     * Called by JNI. Gets the application's database directory, excluding the trailing slash.
+     * @return String The application's database directory
+     */
+    private static synchronized String getDatabaseDirectory() {
+        checkInstanceIsCreated();
+        return sDatabaseDirectory;
+    }
+
+    /**
+     * Called by JNI. Gets the application's cache directory, excluding the trailing slash.
+     * @return String The application's cache directory
+     */
+    private static synchronized String getCacheDirectory() {
+        checkInstanceIsCreated();
+        return sCacheDirectory;
+    }
 }
diff --git a/core/java/android/webkit/L10nUtils.java b/core/java/android/webkit/L10nUtils.java
new file mode 100644
index 0000000..962492e
--- /dev/null
+++ b/core/java/android/webkit/L10nUtils.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.content.Context;
+
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @hide
+ */
+public class L10nUtils {
+
+    // These array elements must be kept in sync with those defined in
+    // external/chromium/android/app/l10n_utils.h
+    private static int[] mIdsArray = {
+        com.android.internal.R.string.autofill_address_name_separator,      // IDS_AUTOFILL_DIALOG_ADDRESS_NAME_SEPARATOR
+        com.android.internal.R.string.autofill_address_summary_name_format, // IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_NAME_FORMAT
+        com.android.internal.R.string.autofill_address_summary_separator,   // IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR
+        com.android.internal.R.string.autofill_address_summary_format       // IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_FORMAT
+    };
+
+    private static List<String> mStrings;
+
+    public static void loadStrings(Context context) {
+        if (mStrings != null) {
+            return;
+        }
+
+        mStrings = new Vector<String>(mIdsArray.length);
+        for (int i = 0; i < mIdsArray.length; i++) {
+            mStrings.add(context.getResources().getString(mIdsArray[i]));
+        }
+    }
+
+    public static String getLocalisedString(int id) {
+        return mStrings.get(id);
+    }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 908a6ab..72b4e36 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -917,6 +917,8 @@
         if (privateBrowsing) {
             startPrivateBrowsing();
         }
+
+        L10nUtils.loadStrings(context);
     }
 
     /*
@@ -6047,7 +6049,7 @@
     }
 
     private void doMotionUp(int contentX, int contentY) {
-        if (mLogEvent && nativeMotionUp(contentX, contentY, mNavSlop)) {
+        if (nativeMotionUp(contentX, contentY, mNavSlop) && mLogEvent) {
             EventLog.writeEvent(EventLogTags.BROWSER_SNAP_CENTER);
         }
         if (nativeHasCursorNode() && !nativeCursorIsTextInput()) {
@@ -6447,7 +6449,7 @@
                     mUserScroll = false;
                     final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj;
                     setBaseLayer(draw.mBaseLayer, draw.mInvalRegion.getBounds());
-                    final Point viewSize = draw.mViewPoint;
+                    final Point viewSize = draw.mViewSize;
                     WebViewCore.ViewState viewState = draw.mViewState;
                     boolean isPictureAfterFirstLayout = viewState != null;
                     if (isPictureAfterFirstLayout) {
@@ -6470,8 +6472,8 @@
                     // received in the fixed dimension.
                     final boolean updateLayout = viewSize.x == mLastWidthSent
                             && viewSize.y == mLastHeightSent;
-                    recordNewContentSize(draw.mWidthHeight.x,
-                            draw.mWidthHeight.y, updateLayout);
+                    recordNewContentSize(draw.mContentSize.x,
+                            draw.mContentSize.y, updateLayout);
                     if (DebugFlags.WEB_VIEW) {
                         Rect b = draw.mInvalRegion.getBounds();
                         Log.v(LOGTAG, "NEW_PICTURE_MSG_ID {" +
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 1c8e2cd..9a873b6 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -260,9 +260,11 @@
      * Given mimeType, check whether it's supported in Android media framework.
      * mimeType could be such as "audio/ogg" and "video/mp4".
      */
-    /* package */ static boolean supportsMimeType(String mimeType) {
-        return MediaFile.getFileTypeForMimeType(mimeType) > 0;
+    /* package */ static boolean isSupportedMediaMimeType(String mimeType) {
+        int fileType = MediaFile.getFileTypeForMimeType(mimeType);
+        return MediaFile.isAudioFileType(fileType) || MediaFile.isVideoFileType(fileType);
     }
+
     /**
      * Add an error message to the client's console.
      * @param message The message to add
@@ -1824,12 +1826,13 @@
         DrawData() {
             mBaseLayer = 0;
             mInvalRegion = new Region();
-            mWidthHeight = new Point();
+            mContentSize = new Point();
         }
         int mBaseLayer;
         Region mInvalRegion;
-        Point mViewPoint;
-        Point mWidthHeight;
+        // view size that was used by webkit during the most recent layout
+        Point mViewSize;
+        Point mContentSize;
         int mMinPrefWidth;
         // only non-null if it is for the first picture set after the first layout
         ViewState mViewState;
@@ -1840,16 +1843,14 @@
         mDrawIsScheduled = false;
         DrawData draw = new DrawData();
         if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw start");
-        draw.mBaseLayer = nativeRecordContent(draw.mInvalRegion, draw.mWidthHeight);
+        draw.mBaseLayer = nativeRecordContent(draw.mInvalRegion, draw.mContentSize);
         if (draw.mBaseLayer == 0) {
             if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort");
             return;
         }
         if (mWebView != null) {
-            // Send the native view size that was used during the most recent
-            // layout.
             draw.mFocusSizeChanged = nativeFocusBoundsChanged();
-            draw.mViewPoint = new Point(mCurrentViewWidth, mCurrentViewHeight);
+            draw.mViewSize = new Point(mCurrentViewWidth, mCurrentViewHeight);
             if (mSettings.getUseWideViewPort()) {
                 draw.mMinPrefWidth = Math.max(
                         mViewportWidth == -1 ? WebView.DEFAULT_VIEWPORT_WIDTH
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 91c0fb2..86dfd1f 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -793,9 +793,9 @@
                 // bound to match the default scale for mobile sites.
                 setZoomOverviewWidth(Math.min(WebView.sMaxViewportWidth,
                     Math.max((int) (viewWidth * mInvDefaultScale),
-                            Math.max(drawData.mMinPrefWidth, drawData.mViewPoint.x))));
+                            Math.max(drawData.mMinPrefWidth, drawData.mViewSize.x))));
             } else {
-                final int contentWidth = drawData.mWidthHeight.x;
+                final int contentWidth = drawData.mContentSize.x;
                 setZoomOverviewWidth(Math.min(WebView.sMaxViewportWidth, contentWidth));
             }
         }
@@ -826,16 +826,16 @@
         assert mWebView.getSettings() != null;
 
         WebViewCore.ViewState viewState = drawData.mViewState;
-        final Point viewSize = drawData.mViewPoint;
+        final Point viewSize = drawData.mViewSize;
         updateZoomRange(viewState, viewSize.x, drawData.mMinPrefWidth);
         if (mWebView.getSettings().getUseWideViewPort() &&
             mWebView.getSettings().getUseFixedViewport()) {
-            final int contentWidth = drawData.mWidthHeight.x;
+            final int contentWidth = drawData.mContentSize.x;
             setZoomOverviewWidth(Math.min(WebView.sMaxViewportWidth, contentWidth));
         }
 
         if (!mWebView.drawHistory()) {
-            final float scale;
+            float scale;
             final boolean reflowText;
             WebSettings settings = mWebView.getSettings();
 
@@ -847,12 +847,13 @@
                 scale = viewState.mViewScale;
                 reflowText = false;
             } else {
+                scale = getZoomOverviewScale();
                 if (settings.getUseWideViewPort()
-                    && (settings.getLoadWithOverviewMode() || settings.getUseFixedViewport())) {
+                    && settings.getLoadWithOverviewMode()) {
                     mInitialZoomOverview = true;
-                    scale = (float) mWebView.getViewWidth() / mZoomOverviewWidth;
                 } else {
-                    scale = viewState.mTextWrapScale;
+                    scale = Math.max(viewState.mTextWrapScale, scale);
+                    mInitialZoomOverview = !exceedsMinScaleIncrement(scale, getZoomOverviewScale());
                 }
                 reflowText = exceedsMinScaleIncrement(mTextWrapScale, scale);
             }
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 0e92eeb..e6d5984 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -114,6 +114,7 @@
     private int mTouchSlop;
     private int mMaximumVelocity;
     private VelocityTracker mVelocityTracker;
+    private boolean mTransitionIsSetup = false;
 
     private static HolographicHelper sHolographicHelper;
     private ImageView mHighlight;
@@ -225,6 +226,48 @@
         }
     }
 
+    private void setupStackSlider(View v, int mode) {
+        mStackSlider.setMode(mode);
+        if (v != null) {
+            mHighlight.setImageBitmap(sHolographicHelper.createOutline(v));
+            mHighlight.setRotation(v.getRotation());
+            mHighlight.setTranslationY(v.getTranslationY());
+            mHighlight.bringToFront();
+            v.bringToFront();
+            mStackSlider.setView(v);
+
+            v.setVisibility(VISIBLE);
+        }
+    }
+
+    @Override
+    @android.view.RemotableViewMethod
+    public void showNext() {
+        if (!mTransitionIsSetup) {
+            View v = getViewAtRelativeIndex(1);
+            if (v != null) {
+                setupStackSlider(v, StackSlider.NORMAL_MODE);
+                mStackSlider.setYProgress(0);
+                mStackSlider.setXProgress(0);
+            }
+        }
+        super.showNext();
+    }
+
+    @Override
+    @android.view.RemotableViewMethod
+    public void showPrevious() {
+        if (!mTransitionIsSetup) {
+            View v = getViewAtRelativeIndex(0);
+            if (v != null) {
+                setupStackSlider(v, StackSlider.NORMAL_MODE);
+                mStackSlider.setYProgress(1);
+                mStackSlider.setXProgress(0);
+            }
+        }
+        super.showPrevious();
+    }
+
     private void transformViewAtIndex(int index, View view) {
         float maxPerpectiveShift = mMeasuredHeight * PERSPECTIVE_SHIFT_FACTOR;
 
@@ -256,11 +299,12 @@
         super.showOnly(childIndex, animate, onLayout);
 
         // Here we need to make sure that the z-order of the children is correct
-	for (int i = mCurrentWindowEnd; i >= mCurrentWindowStart; i--) {
+        for (int i = mCurrentWindowEnd; i >= mCurrentWindowStart; i--) {
             int index = modulo(i, getWindowSize());
             View v = mViewsMap.get(index).view;
             if (v != null) v.bringToFront();
         }
+        mTransitionIsSetup = false;
     }
 
     private void updateChildTransforms() {
@@ -364,29 +408,24 @@
                 activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ? 1 : 0;
             }
 
+            int stackMode;
             if (mLoopViews) {
-                mStackSlider.setMode(StackSlider.NORMAL_MODE);
+                stackMode = StackSlider.NORMAL_MODE;
             } else if (mCurrentWindowStartUnbounded + activeIndex == -1) {
                 activeIndex++;
-                mStackSlider.setMode(StackSlider.BEGINNING_OF_STACK_MODE);
+                stackMode = StackSlider.BEGINNING_OF_STACK_MODE;
             } else if (mCurrentWindowStartUnbounded + activeIndex == mAdapter.getCount() - 1) {
-                mStackSlider.setMode(StackSlider.END_OF_STACK_MODE);
+                stackMode = StackSlider.END_OF_STACK_MODE;
             } else {
-                mStackSlider.setMode(StackSlider.NORMAL_MODE);
+                stackMode = StackSlider.NORMAL_MODE;
             }
 
+            mTransitionIsSetup = stackMode == StackSlider.NORMAL_MODE;
+
             View v = getViewAtRelativeIndex(activeIndex);
             if (v == null) return;
 
-            mHighlight.setImageBitmap(sHolographicHelper.createOutline(v));
-            mHighlight.setRotation(v.getRotation());
-            mHighlight.setTranslationY(v.getTranslationY());
-            mHighlight.bringToFront();
-            v.bringToFront();
-            mStackSlider.setView(v);
-
-            if (swipeGestureType == GESTURE_SLIDE_DOWN)
-                v.setVisibility(VISIBLE);
+            setupStackSlider(v, stackMode);
 
             // We only register this gesture if we've made it this far without a problem
             mSwipeGestureType = swipeGestureType;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6897537..257dbf0 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6903,14 +6903,14 @@
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         final int action = event.getActionMasked();
-        if (action == MotionEvent.ACTION_DOWN) {
-            if (mInsertionPointCursorController != null) {
-                mInsertionPointCursorController.onTouchEvent(event);
-            }
-            if (mSelectionModifierCursorController != null) {
-                mSelectionModifierCursorController.onTouchEvent(event);
-            }
+        if (mInsertionPointCursorController != null) {
+            mInsertionPointCursorController.onTouchEvent(event);
+        }
+        if (mSelectionModifierCursorController != null) {
+            mSelectionModifierCursorController.onTouchEvent(event);
+        }
 
+        if (action == MotionEvent.ACTION_DOWN) {
             // Reset this state; it will be re-set if super.onTouchEvent
             // causes focus to move to the view.
             mTouchFocusSelected = false;
@@ -6931,13 +6931,6 @@
 
         if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()
                 && mText instanceof Spannable && mLayout != null) {
-            if (mInsertionPointCursorController != null) {
-                mInsertionPointCursorController.onTouchEvent(event);
-            }
-            if (mSelectionModifierCursorController != null) {
-                mSelectionModifierCursorController.onTouchEvent(event);
-            }
-
             boolean handled = false;
 
             // Save previous selection, in case this event is used to show the IME.
@@ -6946,7 +6939,7 @@
 
             final int oldScrollX = mScrollX;
             final int oldScrollY = mScrollY;
-            
+
             if (mMovement != null) {
                 handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
             }
@@ -7981,7 +7974,7 @@
                 }
                 mDrawable = mSelectHandleLeft;
                 handleWidth = mDrawable.getIntrinsicWidth();
-                mHotspotX = handleWidth / 4 * 3;
+                mHotspotX = (handleWidth * 3) / 4;
                 break;
             }
 
@@ -8264,6 +8257,11 @@
         // Whether selection anchors are active
         private boolean mIsShowing;
 
+        // Double tap detection
+        private long mPreviousTapUpTime = 0;
+        private int mPreviousTapPositionX;
+        private int mPreviousTapPositionY;
+
         private static final int DELAY_BEFORE_FADE_OUT = 4100;
 
         private final Runnable mHider = new Runnable() {
@@ -8369,6 +8367,26 @@
                         // Remember finger down position, to be able to start selection from there
                         mMinTouchOffset = mMaxTouchOffset = getOffset(x, y);
 
+                        // Double tap detection
+                        long duration = SystemClock.uptimeMillis() - mPreviousTapUpTime;
+                        if (duration <= ViewConfiguration.getDoubleTapTimeout()) {
+                            final int deltaX = x - mPreviousTapPositionX;
+                            final int deltaY = y - mPreviousTapPositionY;
+                            final int distanceSquared = deltaX * deltaX + deltaY * deltaY;
+                            final int doubleTapSlop =
+                                ViewConfiguration.get(getContext()).getScaledDoubleTapSlop();
+                            final int slopSquared = doubleTapSlop * doubleTapSlop;
+                            if (distanceSquared < slopSquared) {
+                                startSelectionActionMode();
+                                // Hacky: onTapUpEvent will open a context menu with cut/copy
+                                // Prevent this by hiding handles which will be revived instead.
+                                hide();
+                            }
+                        }
+
+                        mPreviousTapPositionX = x;
+                        mPreviousTapPositionY = y;
+
                         break;
 
                     case MotionEvent.ACTION_POINTER_DOWN:
@@ -8380,6 +8398,10 @@
                             updateMinAndMaxOffsets(event);
                         }
                         break;
+
+                    case MotionEvent.ACTION_UP:
+                        mPreviousTapUpTime = SystemClock.uptimeMillis();
+                        break;
                 }
             }
             return false;
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index da0c5a2..c473fd2 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -681,19 +681,6 @@
             throws ZygoteInit.MethodAndArgsCaller {
 
         /*
-         * First, set the capabilities if necessary
-         */
-
-        if (parsedArgs.uid != 0) {
-            try {
-                ZygoteInit.setCapabilities(parsedArgs.permittedCapabilities,
-                        parsedArgs.effectiveCapabilities);
-            } catch (IOException ex) {
-                Log.e(TAG, "Error setting capabilities", ex);
-            }
-        }
-
-        /*
          * Close the socket, unless we're in "peer wait" mode, in which
          * case it's used to track the liveness of this process.
          */
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 1d54c61..848bf9e 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -492,18 +492,6 @@
     private static void handleSystemServerProcess(
             ZygoteConnection.Arguments parsedArgs)
             throws ZygoteInit.MethodAndArgsCaller {
-        /*
-         * First, set the capabilities if necessary
-         */
-
-        if (parsedArgs.uid != 0) {
-            try {
-                setCapabilities(parsedArgs.permittedCapabilities,
-                                parsedArgs.effectiveCapabilities);
-            } catch (IOException ex) {
-                Log.e(TAG, "Error setting capabilities", ex);
-            }
-        }
 
         closeServerSocket();
 
@@ -552,7 +540,9 @@
             /* Request to fork the system server process */
             pid = Zygote.forkSystemServer(
                     parsedArgs.uid, parsedArgs.gid,
-                    parsedArgs.gids, debugFlags, null);
+                    parsedArgs.gids, debugFlags, null,
+                    parsedArgs.permittedCapabilities,
+                    parsedArgs.effectiveCapabilities);
         } catch (IllegalArgumentException ex) {
             throw new RuntimeException(ex);
         }
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 34a5b11..f87ca3e 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -32,5 +32,6 @@
     void animateCollapse();
     void setLightsOn(boolean on);
     void setMenuKeyVisible(boolean visible);
+    void setIMEButtonVisible(boolean visible);
 }
 
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 90f4d48..d5ae1f0 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -32,6 +32,7 @@
     void removeIcon(String slot);
     void setActiveWindowIsFullscreen(boolean fullscreen);
     void setMenuKeyVisible(boolean visible);
+    void setIMEButtonVisible(boolean visible);
 
     // ---- Methods below are for use by the status bar policy services ----
     // You need the STATUS_BAR_SERVICE permission
diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java
index 15b9290..b0778dd 100644
--- a/core/java/com/android/internal/util/AsyncChannel.java
+++ b/core/java/com/android/internal/util/AsyncChannel.java
@@ -246,7 +246,6 @@
                 mToken = token;
             }
 
-            @Override
             public void run() {
                 connectSrcHandlerToPackage(mSrcCtx, mSrcHdlr, mDstPackageName, mDstClassName,
                         mToken);
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index bffec1d..ca1cd59 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -18,6 +18,7 @@
 
 import android.os.ResultReceiver;
 import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
 import android.view.inputmethod.EditorInfo;
 import com.android.internal.view.InputBindResult;
 import com.android.internal.view.IInputContext;
@@ -54,6 +55,8 @@
     void hideMySoftInput(in IBinder token, int flags);
     void showMySoftInput(in IBinder token, int flags);
     void updateStatusIcon(in IBinder token, String packageName, int iconId);
+    void setIMEButtonVisible(in IBinder token, boolean visible);
+    InputMethodSubtype getCurrentInputMethodSubtype();
     
     boolean setInputMethodEnabled(String id, boolean enabled);
 }
diff --git a/core/java/com/android/internal/view/InputMethodAndSubtypeEnabler.java b/core/java/com/android/internal/view/InputMethodAndSubtypeEnabler.java
deleted file mode 100644
index 200d49f..0000000
--- a/core/java/com/android/internal/view/InputMethodAndSubtypeEnabler.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.Preference;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceCategory;
-import android.preference.PreferenceScreen;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
-public class InputMethodAndSubtypeEnabler extends PreferenceActivity {
-
-    private boolean mHaveHardKeyboard;
-
-    private List<InputMethodInfo> mInputMethodProperties;
-
-    private final TextUtils.SimpleStringSplitter mStringColonSplitter
-            = new TextUtils.SimpleStringSplitter(':');
-
-    private String mLastInputMethodId;
-    private String mLastTickedInputMethodId;
-
-    private AlertDialog mDialog = null;
-
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        Configuration config = getResources().getConfiguration();
-        mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
-        onCreateIMM();
-        setPreferenceScreen(createPreferenceHierarchy());
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        loadInputMethodSubtypeList();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        saveInputMethodSubtypeList();
-    }
-
-    @Override
-    public boolean onPreferenceTreeClick(
-            PreferenceScreen preferenceScreen, Preference preference) {
-
-        if (preference instanceof CheckBoxPreference) {
-            final CheckBoxPreference chkPref = (CheckBoxPreference) preference;
-            final String id = chkPref.getKey();
-            // TODO: Check subtype or not here
-            if (chkPref.isChecked()) {
-                InputMethodInfo selImi = null;
-                final int N = mInputMethodProperties.size();
-                for (int i = 0; i < N; i++) {
-                    InputMethodInfo imi = mInputMethodProperties.get(i);
-                    if (id.equals(imi.getId())) {
-                        selImi = imi;
-                        if (isSystemIme(imi)) {
-                            setSubtypesPreferenceEnabled(id, true);
-                            // This is a built-in IME, so no need to warn.
-                            mLastTickedInputMethodId = id;
-                            return super.onPreferenceTreeClick(preferenceScreen, preference);
-                        }
-                        break;
-                    }
-                }
-                if (selImi == null) {
-                    return super.onPreferenceTreeClick(preferenceScreen, preference);
-                }
-                chkPref.setChecked(false);
-                if (mDialog == null) {
-                    mDialog = (new AlertDialog.Builder(this))
-                            .setTitle(android.R.string.dialog_alert_title)
-                            .setIcon(android.R.drawable.ic_dialog_alert)
-                            .setCancelable(true)
-                            .setPositiveButton(android.R.string.ok,
-                                    new DialogInterface.OnClickListener() {
-                                        public void onClick(DialogInterface dialog, int which) {
-                                            chkPref.setChecked(true);
-                                            setSubtypesPreferenceEnabled(id, true);
-                                            mLastTickedInputMethodId = id;
-                                        }
-
-                            })
-                            .setNegativeButton(android.R.string.cancel,
-                                    new DialogInterface.OnClickListener() {
-                                        public void onClick(DialogInterface dialog, int which) {
-                                        }
-
-                            })
-                            .create();
-                } else {
-                    if (mDialog.isShowing()) {
-                        mDialog.dismiss();
-                    }
-                }
-                mDialog.setMessage(getResources().getString(
-                        com.android.internal.R.string.ime_enabler_security_warning,
-                        selImi.getServiceInfo().applicationInfo.loadLabel(getPackageManager())));
-                mDialog.show();
-            } else {
-                if (id.equals(mLastTickedInputMethodId)) {
-                    mLastTickedInputMethodId = null;
-                }
-                setSubtypesPreferenceEnabled(id, false);
-            }
-        }
-        return super.onPreferenceTreeClick(preferenceScreen, preference);
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        if (mDialog != null) {
-            mDialog.dismiss();
-            mDialog = null;
-        }
-    }
-
-    private void onCreateIMM() {
-        InputMethodManager imm = (InputMethodManager) getSystemService(
-                Context.INPUT_METHOD_SERVICE);
-
-        // TODO: Change mInputMethodProperties to Map
-        mInputMethodProperties = imm.getInputMethodList();
-
-        mLastInputMethodId = Settings.Secure.getString(getContentResolver(),
-                Settings.Secure.DEFAULT_INPUT_METHOD);
-    }
-
-    private PreferenceScreen createPreferenceHierarchy() {
-        // Root
-        PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);
-
-        int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size());
-        // TODO: Use iterator.
-        for (int i = 0; i < N; ++i) {
-            PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(this);
-            root.addPreference(keyboardSettingsCategory);
-            InputMethodInfo property = mInputMethodProperties.get(i);
-            String prefKey = property.getId();
-
-            PackageManager pm = getPackageManager();
-            CharSequence label = property.loadLabel(pm);
-            boolean systemIME = isSystemIme(property);
-
-            keyboardSettingsCategory.setTitle(label);
-
-            // Add a check box.
-            // Don't show the toggle if it's the only keyboard in the system, or it's a system IME.
-            if (mHaveHardKeyboard || (N > 1 && !systemIME)) {
-                CheckBoxPreference chkbxPref = new CheckBoxPreference(this);
-                chkbxPref.setKey(prefKey);
-                chkbxPref.setTitle(label);
-                keyboardSettingsCategory.addPreference(chkbxPref);
-            }
-
-            ArrayList<InputMethodSubtype> subtypes = property.getSubtypes();
-            if (subtypes.size() > 0) {
-                PreferenceCategory subtypesCategory = new PreferenceCategory(this);
-                subtypesCategory.setTitle(getResources().getString(
-                        com.android.internal.R.string.ime_enabler_subtype_title, label));
-                root.addPreference(subtypesCategory);
-                for (InputMethodSubtype subtype: subtypes) {
-                    CharSequence subtypeLabel;
-                    int nameResId = subtype.getNameResId();
-                    if (nameResId != 0) {
-                        subtypeLabel = pm.getText(property.getPackageName(), nameResId,
-                                property.getServiceInfo().applicationInfo);
-                    } else {
-                        int modeResId = subtype.getModeResId();
-                        CharSequence language = subtype.getLocale();
-                        CharSequence mode = modeResId == 0 ? null
-                                : pm.getText(property.getPackageName(), modeResId,
-                                        property.getServiceInfo().applicationInfo);
-                        // TODO: Use more friendly Title and UI
-                        subtypeLabel = (mode == null ? "" : mode) + ","
-                                + (language == null ? "" : language);
-                    }
-                    CheckBoxPreference chkbxPref = new CheckBoxPreference(this);
-                    chkbxPref.setKey(prefKey + subtype.hashCode());
-                    chkbxPref.setTitle(subtypeLabel);
-                    chkbxPref.setSummary(label);
-                    subtypesCategory.addPreference(chkbxPref);
-                }
-            }
-        }
-        return root;
-    }
-
-    private void loadInputMethodSubtypeList() {
-        final HashSet<String> enabled = new HashSet<String>();
-        String enabledStr = Settings.Secure.getString(getContentResolver(),
-                Settings.Secure.ENABLED_INPUT_METHODS);
-        if (enabledStr != null) {
-            final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
-            splitter.setString(enabledStr);
-            while (splitter.hasNext()) {
-                enabled.add(splitter.next());
-            }
-        }
-
-        // Update the statuses of the Check Boxes.
-        int N = mInputMethodProperties.size();
-        // TODO: Use iterator.
-        for (int i = 0; i < N; ++i) {
-            final String id = mInputMethodProperties.get(i).getId();
-            CheckBoxPreference pref = (CheckBoxPreference) findPreference(
-                    mInputMethodProperties.get(i).getId());
-            if (pref != null) {
-                boolean isEnabled = enabled.contains(id);
-                pref.setChecked(isEnabled);
-                setSubtypesPreferenceEnabled(id, isEnabled);
-            }
-        }
-        mLastTickedInputMethodId = null;
-    }
-
-    private void saveInputMethodSubtypeList() {
-        StringBuilder builder = new StringBuilder();
-        StringBuilder disabledSysImes = new StringBuilder();
-
-        int firstEnabled = -1;
-        int N = mInputMethodProperties.size();
-        for (int i = 0; i < N; ++i) {
-            final InputMethodInfo property = mInputMethodProperties.get(i);
-            final String id = property.getId();
-            CheckBoxPreference pref = (CheckBoxPreference) findPreference(id);
-            boolean currentInputMethod = id.equals(mLastInputMethodId);
-            boolean systemIme = isSystemIme(property);
-            // TODO: Append subtypes by using the separator ";"
-            if (((N == 1 || systemIme) && !mHaveHardKeyboard)
-                    || (pref != null && pref.isChecked())) {
-                if (builder.length() > 0) builder.append(':');
-                builder.append(id);
-                if (firstEnabled < 0) {
-                    firstEnabled = i;
-                }
-            } else if (currentInputMethod) {
-                mLastInputMethodId = mLastTickedInputMethodId;
-            }
-            // If it's a disabled system ime, add it to the disabled list so that it
-            // doesn't get enabled automatically on any changes to the package list
-            if (pref != null && !pref.isChecked() && systemIme && mHaveHardKeyboard) {
-                if (disabledSysImes.length() > 0) disabledSysImes.append(":");
-                disabledSysImes.append(id);
-            }
-        }
-
-        // If the last input method is unset, set it as the first enabled one.
-        if (TextUtils.isEmpty(mLastInputMethodId)) {
-            if (firstEnabled >= 0) {
-                mLastInputMethodId = mInputMethodProperties.get(firstEnabled).getId();
-            } else {
-                mLastInputMethodId = null;
-            }
-        }
-
-        Settings.Secure.putString(getContentResolver(),
-                Settings.Secure.ENABLED_INPUT_METHODS, builder.toString());
-        Settings.Secure.putString(getContentResolver(),
-                Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, disabledSysImes.toString());
-        Settings.Secure.putString(getContentResolver(),
-                Settings.Secure.DEFAULT_INPUT_METHOD,
-                mLastInputMethodId != null ? mLastInputMethodId : "");
-    }
-
-    private void setSubtypesPreferenceEnabled(String id, boolean enabled) {
-        PreferenceScreen preferenceScreen = getPreferenceScreen();
-        final int N = mInputMethodProperties.size();
-        // TODO: Use iterator.
-        for (int i = 0; i < N; i++) {
-            InputMethodInfo imi = mInputMethodProperties.get(i);
-            if (id.equals(imi.getId())) {
-                for (InputMethodSubtype subtype: imi.getSubtypes()) {
-                    preferenceScreen.findPreference(id + subtype.hashCode()).setEnabled(enabled);
-                }
-            }
-        }
-    }
-
-    private boolean isSystemIme(InputMethodInfo property) {
-        return (property.getServiceInfo().applicationInfo.flags
-                & ApplicationInfo.FLAG_SYSTEM) != 0;
-    }
-}
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 27d4b9e..a024420 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -571,6 +571,15 @@
     return doBooleanCommand("BLACKLIST clear", "OK");
 }
 
+static jboolean android_net_wifi_setSuspendOptimizationsCommand(JNIEnv* env, jobject clazz, jboolean enabled)
+{
+    char cmdstr[BUF_SIZE];
+
+    snprintf(cmdstr, sizeof(cmdstr), "DRIVER SETSUSPENDOPT %d", enabled ? 0 : 1);
+    return doBooleanCommand(cmdstr, "OK");
+}
+
+
 static jboolean android_net_wifi_doDhcpRequest(JNIEnv* env, jobject clazz, jobject info)
 {
     jint ipaddr, gateway, mask, dns1, dns2, server, lease;
@@ -657,6 +666,8 @@
         (void*) android_net_wifi_wpsPinFromAccessPointCommand },
     { "startWpsWithPinFromDeviceCommand", "(Ljava/lang/String;)I",
         (void*) android_net_wifi_wpsPinFromDeviceCommand },
+    { "setSuspendOptimizationsCommand", "(Z)Z",
+        (void*) android_net_wifi_setSuspendOptimizationsCommand},
     { "doDhcpRequest", "(Landroid/net/DhcpInfo;)Z", (void*) android_net_wifi_doDhcpRequest },
     { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_wifi_getDhcpError },
 };
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 122fdf8..2444fce 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -88,7 +88,6 @@
     <protected-broadcast android:name="android.hardware.action.USB_CAMERA_ATTACHED" />
     <protected-broadcast android:name="android.hardware.action.USB_CAMERA_DETACHED" />
 
-    <protected-broadcast android:name="android.nfc.action.NDEF_TAG_DISCOVERED" />
     <protected-broadcast android:name="android.nfc.action.TAG_DISCOVERED" />
     <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
     <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
@@ -1352,11 +1351,6 @@
                 android:permission="android.permission.BIND_WALLPAPER">
         </service>
 
-        <activity android:name="com.android.internal.view.InputMethodAndSubtypeEnabler"
-                android:excludeFromRecents="true"
-                android:exported="true">
-        </activity>
-
         <receiver android:name="com.android.server.BootReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
diff --git a/core/res/res/anim/wallpaper_intra_close_enter.xml b/core/res/res/anim/wallpaper_intra_close_enter.xml
index 5c4f5c9..73bf9a3 100644
--- a/core/res/res/anim/wallpaper_intra_close_enter.xml
+++ b/core/res/res/anim/wallpaper_intra_close_enter.xml
@@ -20,12 +20,6 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator"
         android:zAdjustment="top">
-    <scale android:fromXScale="2.0" android:toXScale="1.0"
-           android:fromYScale="2.0" android:toYScale="1.0"
-           android:pivotX="100%p" android:pivotY="50%p"
-           android:duration="@android:integer/config_mediumAnimTime" />
-	<translate android:fromXDelta="-150%p" android:toXDelta="0%p"
-        android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-            android:duration="@android:integer/config_mediumAnimTime" />
+    <alpha android:fromAlpha="0.5" android:toAlpha="1.0"
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/wallpaper_intra_close_exit.xml b/core/res/res/anim/wallpaper_intra_close_exit.xml
index acaf773..d43660e 100644
--- a/core/res/res/anim/wallpaper_intra_close_exit.xml
+++ b/core/res/res/anim/wallpaper_intra_close_exit.xml
@@ -18,13 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/accelerate_interpolator">
-    <scale android:fromXScale="1.0" android:toXScale=".5"
-           android:fromYScale="1.0" android:toYScale=".5"
-           android:pivotX="100%p" android:pivotY="50%p"
-           android:duration="@android:integer/config_mediumAnimTime" />
-	<translate android:fromXDelta="0%p" android:toXDelta="100%p"
-        android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-            android:duration="@android:integer/config_mediumAnimTime"/>
+        android:interpolator="@anim/decelerate_interpolator">
+    <alpha android:fromAlpha="0.5" android:toAlpha="0.0"
+            android:duration="@android:integer/config_shortAnimTime"/>
 </set>
diff --git a/core/res/res/anim/wallpaper_intra_open_enter.xml b/core/res/res/anim/wallpaper_intra_open_enter.xml
index 81c9991..c85ca4c 100644
--- a/core/res/res/anim/wallpaper_intra_open_enter.xml
+++ b/core/res/res/anim/wallpaper_intra_open_enter.xml
@@ -19,12 +19,6 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator">
-    <scale android:fromXScale=".5" android:toXScale="1.0"
-           android:fromYScale=".5" android:toYScale="1.0"
-           android:pivotX="100%p" android:pivotY="50%p"
-           android:duration="@android:integer/config_mediumAnimTime" />
-    <translate android:fromXDelta="100%p" android:toXDelta="0"
-            android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-            android:duration="@android:integer/config_mediumAnimTime" />
+    <alpha android:fromAlpha="0.5" android:toAlpha="1.0"
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/wallpaper_intra_open_exit.xml b/core/res/res/anim/wallpaper_intra_open_exit.xml
index 28c4287..eaeac22 100644
--- a/core/res/res/anim/wallpaper_intra_open_exit.xml
+++ b/core/res/res/anim/wallpaper_intra_open_exit.xml
@@ -18,14 +18,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/accelerate_interpolator"
+        android:interpolator="@anim/decelerate_interpolator"
         android:zAdjustment="top">
-    <scale android:fromXScale="1.0" android:toXScale="2.0"
-           android:fromYScale="1.0" android:toYScale="2.0"
-           android:pivotX="100%p" android:pivotY="50%p"
-           android:duration="@android:integer/config_mediumAnimTime" />
-    <translate android:fromXDelta="0" android:toXDelta="-150%p"
-            android:duration="@android:integer/config_mediumAnimTime"/>
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-            android:duration="@android:integer/config_mediumAnimTime"/>
+    <alpha android:fromAlpha="0.5" android:toAlpha="0.0"
+            android:duration="@android:integer/config_shortAnimTime"/>
 </set>
diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_dark.png b/core/res/res/drawable-hdpi/ic_menu_copy_dark.png
new file mode 100644
index 0000000..852f146
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_copy_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_light.png b/core/res/res/drawable-hdpi/ic_menu_copy_light.png
new file mode 100644
index 0000000..ad09b37
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_copy_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_dark.png b/core/res/res/drawable-hdpi/ic_menu_cut_dark.png
new file mode 100644
index 0000000..7716a94
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_cut_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_light.png b/core/res/res/drawable-hdpi/ic_menu_cut_light.png
new file mode 100644
index 0000000..bea6db1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_cut_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_dark.png b/core/res/res/drawable-hdpi/ic_menu_paste_dark.png
new file mode 100644
index 0000000..5579443
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_paste_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_light.png b/core/res/res/drawable-hdpi/ic_menu_paste_light.png
new file mode 100644
index 0000000..6674914
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_paste_light.png
Binary files differ
diff --git a/core/res/res/layout-port/preference_header_item.xml b/core/res/res/layout-port/preference_header_item.xml
deleted file mode 100644
index cc76c8e..0000000
--- a/core/res/res/layout-port/preference_header_item.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<!-- Layout of a header item in PreferenceActivity. -->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="96dp"
-    android:background="?android:attr/activatedBackgroundIndicator"
-    android:paddingRight="?android:attr/scrollbarSize">
-    
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:layout_gravity="center"
-        android:paddingLeft="4dip"
-        android:paddingRight="4dip"
-        android:paddingTop="4dip"
-        android:paddingBottom="4dip">
-    
-        <ImageView
-            android:id="@+id/icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:layout_marginBottom="2dip" />
-    
-        <TextView android:id="@+android:id/title"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:layout_marginBottom="2dip"
-            android:singleLine="true"
-            android:textAppearance="?android:attr/textAppearanceLarge"
-            android:ellipsize="marquee"
-            android:fadingEdge="horizontal" />
-    
-        <TextView android:id="@+android:id/summary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:gravity="center"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:ellipsize="end"
-            android:maxLines="2" />
-    
-    </LinearLayout>
-</FrameLayout>
diff --git a/core/res/res/layout/preference_header_item.xml b/core/res/res/layout/preference_header_item.xml
index aba7b2ad..f00e7aa 100644
--- a/core/res/res/layout/preference_header_item.xml
+++ b/core/res/res/layout/preference_header_item.xml
@@ -18,7 +18,7 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:minHeight="48dp"
     android:background="?android:attr/activatedBackgroundIndicator"
     android:gravity="center_vertical"
     android:paddingRight="?android:attr/scrollbarSize">
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index 7c0b791..5b42407 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -21,7 +21,8 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_height="match_parent"
-    android:layout_width="match_parent">
+    android:layout_width="match_parent"
+    android:background="@android:color/transparent">
 
     <LinearLayout
         android:orientation="horizontal"
@@ -34,6 +35,10 @@
             android:orientation="vertical"
             android:layout_width="0px"
             android:layout_height="match_parent"
+            android:layout_marginLeft="32dp"
+            android:layout_marginTop="32dp"
+            android:layout_marginRight="16dp"
+            android:layout_marginBottom="32dp"
             android:layout_weight="10">
 
             <ListView android:id="@android:id/list"
@@ -41,6 +46,9 @@
                 android:layout_height="0px"
                 android:layout_weight="1"
                 android:drawSelectorOnTop="false"
+                android:background="#40404040"
+                android:cacheColorHint="@android:color/transparent"
+                android:listPreferredItemHeight="48dp"
                 android:scrollbarAlwaysDrawVerticalTrack="true" />
 
             <FrameLayout android:id="@+id/list_footer"
@@ -53,7 +61,12 @@
         <FrameLayout android:id="@+id/prefs"
                 android:layout_width="0px"
                 android:layout_height="match_parent"
-                android:layout_weight="33"
+                android:layout_weight="25"
+                android:layout_marginLeft="16dp"
+                android:layout_marginRight="16dp"
+                android:layout_marginTop="16dp"
+                android:layout_marginBottom="16dp"
+                android:background="#60202040"
                 android:visibility="gone" />
     </LinearLayout>
 
diff --git a/core/res/res/layout/preference_list_fragment.xml b/core/res/res/layout/preference_list_fragment.xml
new file mode 100644
index 0000000..c499b8a
--- /dev/null
+++ b/core/res/res/layout/preference_list_fragment.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:background="@android:color/transparent">
+
+    <ListView android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="0px"
+        android:layout_weight="1"
+        android:drawSelectorOnTop="false"
+        android:cacheColorHint="@android:color/transparent"
+        android:scrollbarAlwaysDrawVerticalTrack="true" />
+
+    <RelativeLayout android:id="@+id/button_bar"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:layout_weight="0"
+        android:background="@android:drawable/bottom_bar"
+        android:visibility="gone">
+
+        <Button android:id="@+id/back_button"
+            android:layout_width="150dip"
+            android:layout_height="wrap_content"
+            android:layout_margin="5dip"
+            android:layout_alignParentLeft="true"
+            android:drawableLeft="@drawable/ic_btn_back"
+            android:drawablePadding="3dip"
+            android:text="@string/back_button_label"
+        />
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true">
+
+            <Button android:id="@+id/skip_button"
+                android:layout_width="150dip"
+                android:layout_height="wrap_content"
+                android:layout_margin="5dip"
+                android:text="@string/skip_button_label"
+                android:visibility="gone"
+            />
+
+            <Button android:id="@+id/next_button"
+                android:layout_width="150dip"
+                android:layout_height="wrap_content"
+                android:layout_margin="5dip"
+                android:drawableRight="@drawable/ic_btn_next"
+                android:drawablePadding="3dip"
+                android:text="@string/next_button_label"
+            />
+        </LinearLayout>
+    </RelativeLayout>
+</LinearLayout>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index e6c0a48..8399db0 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Vypnout"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Vypínání..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Váš telefon bude vypnut."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nejnovější"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Žádné nedávno použité aplikace."</string>
     <string name="global_actions" msgid="2406416831541615258">"Možnosti telefonu"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Nástroje pro vývojáře"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funkce pouze pro vývojáře aplikací"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Úložiště"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Přístup ke kartě SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Přístup do úložiště USB."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Přístup ke kartě SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"zakázání či změny stavového řádku"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"stavový řádek"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Umožňuje aplikaci uvolnit paměť telefonu smazáním souborů v adresáři mezipaměti aplikace. Přístup je velmi omezený, většinou pouze pro systémové procesy."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Přesun zdrojů aplikace"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Umožňuje aplikaci přesunout své zdroje z interní paměti na externí médium a opačně."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"číst citlivá data v protokolech"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Umožňuje aplikaci číst různé systémové soubory protokolů. Toto nastavení aplikaci umožní získat obecné informace o činnostech s telefonem, které by mohly obsahovat osobní či soukromé informace."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"čtení nebo zápis do prostředků funkce diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Umožňuje aplikaci číst libovolné prostředky ve skupině diag, např. soubory ve složce /dev, a zapisovat do nich. Může dojít k ovlivnění stability a bezpečnosti systému. Toto nastavení by měl používat pouze výrobce či operátor pro diagnostiku hardwaru."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"povolení či zakázání komponent aplikací"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Umožňuje aplikaci připojit či odpojit souborové systémy ve vyměnitelných úložištích."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formátovat externí úložiště"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Umožňuje aplikaci formátovat vyměnitelná úložiště."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"získat informace o zabezpečeném úložišti"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Umožňuje aplikaci získat informace o zabezpečeném úložišti."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"vytvořit zabezpečené úložiště"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Umožňuje aplikaci vytvořit zabezpečené úložiště."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"zničit zabezpečené úložiště"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Umožňuje aplikaci zničit zabezpečené úložiště."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"připojit nebo odpojit zabezpečené úložiště"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Umožňuje aplikaci připojit nebo odpojit zabezpečené úložiště."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"přejmenovat zabezpečené úložiště"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Umožňuje aplikaci přejmenovat zabezpečeného úložiště."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"získat informace o interním úložišti"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Umožňuje aplikaci získat informace o interním úložišti."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"vytvořit interní úložiště"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Umožňuje aplikaci vytvořit interní úložiště."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"trvale smazat interní úložiště"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Umožňuje aplikaci trvale smazat interní úložiště."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"připojit nebo odpojit interní úložiště"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Umožňuje aplikaci připojit nebo odpojit interní úložiště."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"přejmenovat interní úložiště"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Umožňuje aplikaci přejmenovat interní úložiště."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"ovládání vibrací"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Umožňuje aplikaci ovládat vibrace."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"ovládání kontrolky"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Umožňuje aplikaci konfigurovat místní telefon s rozhraním Bluetooth a vyhledávat a párovat vzdálená zařízení."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"vytvoření připojení Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Umožňuje aplikaci zobrazit konfiguraci místního telefonu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"ovládat technologii NFC"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Umožňuje aplikaci komunikovat se štítky, kartami a čtečkami s podporou technologie NFC."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"vypnutí zámku kláves"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Umožňuje aplikaci vypnout zámek kláves a související zabezpečení heslem. Příkladem oprávněného použití této funkce je vypnutí zámku klávesnice při příchozím hovoru a jeho opětovné zapnutí po skončení hovoru."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čtení nastavení synchronizace"</string>
@@ -420,23 +423,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Umožní aplikaci číst soukromá slova, jména a fráze, která uživatel mohl uložit do svého slovníku."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"zápis do slovníku definovaného uživatelem"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Umožní aplikaci zapisovat nová slova do uživatelského slovníku."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"změna/smazání obsahu karty SD"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Umožní aplikaci zápis na kartu SD."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"upravit/smazat obsah úlož. USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"změna/smazání obsahu karty SD"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Umožní zápis do úložiště USB."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Umožní aplikaci zápis na kartu SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"přistupovat do souborového systému mezipaměti"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Umožňuje aplikaci číst a zapisovat do souborového systému mezipaměti."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Omezení hesla"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Omezuje typ hesel, která lze použít."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Sledování pokusů o přihlášení"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Sleduje nezdařené pokusy o přihlášení do zařízení a umožňuje provedení určité akce."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Obnovení hesla"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Vynutí nastavení hesla na novou hodnotu, kterou vám před přihlášením musí sdělit správce."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Vynucení uzamčení"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Určuje, kdy dojde k uzamčení zařízení a bude požadováno opětovné zadání hesla."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"uskutečňovat a přijímat internetové hovory"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Umožňuje aplikaci uskutečnit a přijímat internetové hovory pomocí služby SIP."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Řídit délku hesel pro odemčení obrazovky a v nich používané znaky"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemčení obrazovky"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout telefon nebo odstranit veškerá data telefonu, pokud dojde k příliš mnoha neplatným pokusům o zadání hesla"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Změnit heslo pro odemknutí obrazovky"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Změnit heslo pro odemknutí obrazovky"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Uzamknout obrazovku"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Řídit, jak a kdy se obrazovka uzamkne"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Vymazání všech dat"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Bez dalšího potvrzení obnoví výchozí nastavení z výroby a smaže všechna data."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Nastavte globální server proxy, který je používán, když jsou zásady aktivní. Platný globální server proxy nastavuje pouze první správce zařízení."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Bez upozornění smazat všechna data telefonu obnovením továrních dat"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nastavit globální proxy server zařízení"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Vyberte globální proxy server, který se bude používat, když jsou zásady aktivní. Aktuální globální proxy server nastavuje pouze první správce zařízení."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domů"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Práce"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Jiné"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Vlastní"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Vlastní"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Plocha"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Práce"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Jiné"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Zadejte kód PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Zadejte heslo pro odblokování"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Zadejte kód PIN pro odblokování"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Tip: Dvojitým klepnutím můžete zobrazení přiblížit nebo oddálit."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Automaticky vyplnit tento formulář"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Umožní aplikaci změnit historii či záložky prohlížeče uložené v telefonu. Škodlivé aplikace mohou pomocí tohoto nastavení vymazat či pozměnit data Prohlížeče."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"nastavit budík v budíku"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Dovoluje aplikaci nastavit budík v nainstalované aplikaci budíku. Některé budíkové aplikace nemusí tuto funkci implementovat."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Změnit oprávnění prohlížeče poskytovat informace o zeměpisné poloze"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Umožňuje aplikaci změnit oprávnění prohlížeče poskytovat informace o zeměpisné poloze. Škodlivé aplikace mohou toto nastavení použít k odesílání informací o umístění na libovolné webové stránky."</string>
     <string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prohlížeč zapamatoval toto heslo?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Ukončit aplikaci"</string>
     <string name="report" msgid="4060218260984795706">"Nahlásit"</string>
     <string name="wait" msgid="7147118217226317732">"Počkat"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Aplikace přesměrována"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"Je spuštěna aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Původně byla spuštěna aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="smv_application" msgid="295583804361236288">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) porušila své vlastní vynucené zásady StrictMode."</string>
     <string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> porušil své vlastní vynucené zásady StrictMode."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Běží aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Zobrazit vše"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Úložiště USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB připojeno"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Připojili jste svůj telefon k počítači pomocí USB. Chcete-li kopírovat soubory z počítače na kartu SD v zařízení Android či obráceně, vyberte následující tlačítko."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Připojili jste telefon k počítači pomocí rozhraní USB. Chcete-li kopírovat soubory z počítače do úložiště USB zařízení Android či obráceně, vyberte následující tlačítko."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Připojili jste svůj telefon k počítači pomocí USB. Chcete-li kopírovat soubory z počítače na kartu SD v zařízení Android či obráceně, vyberte následující tlačítko."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Zapnout úložiště USB"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Při používání vaší karty SD jako úložiště USB došlo k problému."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Problém s použitím úložiště USB jako velkokapacitního úložiště."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Problém s použitím karty SD jako velkokapacitního úložiště USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB připojeno"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Vyberte, chcete-li kopírovat soubory do nebo z počítače."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Vypnout úložiště USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Vyberte, chcete-li vypnout úložiště USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Úložiště USB je používáno"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Před vypnutím úložiště USB zkontrolujte, zda jste odpojili (vyjmuli) kartu SD zařízení Android z počítače."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Před vypnutím úložiště USB zkontrolujte, zda jste úložiště USB zařízení Android odpojili z počítače."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Před vypnutím úložiště USB zkontrolujte, zda jste odpojili (vyjmuli) kartu SD zařízení Android z počítače."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Vypnout úložiště USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Při vypínání úložiště USB došlo k problémům. Zkontrolujte, zda byl hostitel USB odpojen, a zkuste to znovu."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Zapnout úložiště USB"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Pokud zapnete úložiště USB, dojde k zastavení některých používaných aplikací. Tyto aplikace pravděpodobně nebudou k dispozici až do vypnutí úložiště USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Chyba operace na rozhraní USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formátovat kartu SD"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Opravdu chcete kartu SD naformátovat? Všechna data na kartě budou ztracena."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formátovat úložiště USB"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formátovat kartu SD"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Chcete úložiště USB zformátovat a tím smazat všechny soubory, které v něm jsou uloženy? Tuto akci nelze vrátit zpět."</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Opravdu chcete kartu SD naformátovat? Všechna data na kartě budou ztracena."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formátovat"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ladění přes rozhraní USB připojeno"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Vyberte, chcete-li zakázat ladění USB."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidáti"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Příprava karty SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Příprava úložiště USB"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Příprava karty SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Kontrola chyb."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Prázdná karta SD"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"Karta SD je prázdná nebo obsahuje nepodporovaný systém souborů."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Poškozená karta SD"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"Karta SD je poškozená. Bude pravděpodobně nutné ji přeformátovat."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"Karta SD byla neočekávaně odebrána"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Chcete-li zabránit ztrátě dat, kartu SD před odebráním odpojte."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"Kartu SD je možné bezpečně odebrat"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Kartu SD lze bezpečně odebrat."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Karta SD byla odstraněna"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"Karta SD byla odebrána. Vložte novou kartu."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Prázdné úložiště USB"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Prázdná karta SD"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Úložiště USB je prázdné nebo obsahuje nepodporovaný systém souborů."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Karta SD je prázdná nebo obsahuje nepodporovaný systém souborů."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Úložiště USB je poškozeno"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Poškozená karta SD"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Úložiště USB je poškozené. Bude pravděpodobně nutné je přeformátovat."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Karta SD je poškozená. Bude pravděpodobně nutné ji přeformátovat."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Úložiště USB nečekaně odebráno"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Karta SD byla neočekávaně odebrána"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Před odebráním úložiště USB ho nejprve odpojte. Zabráníte tak ztrátě dat."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Chcete-li zabránit ztrátě dat, kartu SD před odebráním odpojte."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Úložiště USB lze odebrat"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Kartu SD je možné bezpečně odebrat"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Úložiště USB lze bezpečně odebrat."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Kartu SD lze bezpečně odebrat."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Úložiště USB odebráno"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Karta SD byla odstraněna"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Úložiště USB odebráno. Vložte nové médium."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Karta SD byla odebrána. Vložte novou kartu."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nebyly nalezeny žádné odpovídající aktivity."</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"aktualizovat statistiku použití součástí"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Umožňuje změnu shromážděných statistických údajů o použití součástí. Není určeno pro běžné aplikace."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 shoda"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Odpojování úložiště USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Odpojování karty SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Mazání úložiště USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Mazání karty SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Smazání úložiště USB se nezdařilo."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Smazání karty SD se nezdařilo."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Karta SD nebyla před odebráním odpojena."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Probíhá kontrola úložiště USB."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Probíhá kontrola karty SD."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Karta SD byla odebrána."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Úložiště USB je momentálně používáno počítačem."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Karta SD je momentálně používána počítačem."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Neznámý stav externího média."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index d7e3625..a3efb4a 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Sluk"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Lukker ned ..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Din telefon slukkes nu."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Seneste"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Der er ingen nye programmer."</string>
     <string name="global_actions" msgid="2406416831541615258">"Indstillinger for telefon"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Udviklingsværktøjer"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funktioner kun til programudviklere."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Lagring"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Få adgang til SD-kortet."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Få adgang til USB-lager."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Få adgang til SD-kortet."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"deaktiver eller rediger statuslinje"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Tillader, at et program deaktiverer statuslinjen eller tilføjer eller fjerner systemikoner."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"statusbjælke"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Tillader, at et program frigør plads på telefonen ved at slette filer i programmets cachemappe. Adgang er normalt meget begrænset til systemprocesser."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Flyt programressourcer"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Tillader, at et program flytter programressourcer fra interne til eksterne medier og omvendt."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"læse følsomme logdata"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Tillader, at et program læser fra systemets forskellige logfiler. Dermed kan generelle oplysninger om, hvad du laver med telefonen, registreres, også personlige eller private oplysninger."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"læs/skriv til ressourcer ejet af diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Tillader, at et program læser og skriver til alle ressourcer, der ejes af diag-gruppen, som f.eks. flier i /dev. Dette kan muligvis påvirke systemets stabilitet og sikkerhed. Dette bør KUN bruges til hardwarespecifikke diagnosticeringer foretaget af producent eller udbyder."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"aktiver eller deaktiver programkomponenter"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Tillader, at programmet monterer eller demonterer filsystemer til flytbar lagring."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formater ekstern lagring"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Tillader, at et program formaterer flytbart lager."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"hente oplysninger om sikkert lager"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Tillader programmet at få oplysninger om sikkert lager."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"opret sikkert lager"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Tillader programmet at oprette sikkert lager."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"ødelægge sikkert lager"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Tillader programmet at ødelægge sikkert lager."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"montere/demontere sikkert lager"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Tillader programmet at montere/demontere sikkert lager."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"omdøbe sikkert lager"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Tillader programmet at omdøbe sikkert lager."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"hente oplysninger om internt lager"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Tillader, at programmet får oplysninger om internt lager."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"oprette internt lager"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Tillader, at programmet opretter internt lager."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"ødelægge internt lager"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Tillader, at programmet ødelægger internt lager."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"montere/demontere internt lager"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Tillader, at programmet monterer/demonterer internt lager."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"omdøbe internt lager"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Tillader, at programmet omdøber internt lager."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"kontroller vibrator"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Lader programmet kontrollere vibratoren."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kontroller lommelygte"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Tillader, at et program konfigurerer den lokale Bluetooth-telefon samt opdager og parrer med fjerne enheder."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"opret Bluetooth-forbindelser"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Tillader, at et program viser konfigurationen af den lokale Bluetooth-telefon samt opretter og accepterer forbindelse med parrede enheder."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"kontrollere Near Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Tillader, at et program kommunikerer med tags, kort og læsere i Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"deaktiver tastaturlås"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Tillader, at et program deaktiverer tastaturlåsen og al associeret adgangskodesikkerhed. Et legitimt eksempel på dette er, at telefonen deaktiverer tastaturlåsen, når der modtages et indgående telefonopkald, og genaktiverer tastaturlåsen, når opkaldet er afsluttet."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"læs indstillinger for synkronisering"</string>
@@ -420,22 +423,25 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Tillader, at et program læser alle private ord, navne og sætninger, som brugeren eventuelt har gemt i brugerordbogen."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"skriv til den brugerdefinerede ordbog"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Tillader, at et program skriver nye ord i brugerordbogen."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"ret/slet indholdet på SD-kortet"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Tillader, at et program skriver til SD-kortet."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"rette/slette i USB-lager"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"ret/slet indholdet på SD-kortet"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Tillad skriv til USB-lager."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Tillader, at et program skriver til SD-kortet."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"få adgang til cache-filsystemet"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillader, at et program læser og skriver til cache-filsystemet."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Begræns adgangskode"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Begræns de adgangskodetyper, du har tilladelse til at bruge."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Vis forsøg på at logge ind"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Overvåg mislykkede forsøg på at logge ind på enheden for at foretage en handling."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Nulstil adgangskode"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Tving din adgangskode til en ny værdi. Dette kræver, at administratoren giver den til dig, før du kan kogge ind."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Tvangslås"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Kontrol når enheden låses, så du skal indtaste adgangskoden igen."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"foretage/modtage internetopkald"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Tillader, at et program anvender SIP-tjenesten til at foretage/modtage internetopkald."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærm"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Overvåg antallet af forkerte adgangskoder, som indtastes ved oplåsning af skærmen, og lås telefonen, eller slet alle telefonens data, hvis der er for mange forkerte forsøg"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Skift adgangskode til oplåsning af skærm"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Skift adgangskode til oplåsning af skærm"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Lås skærmen"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Bestem, hvordan og hvornår skærmen låses"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Slet alle data"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Foretag en fabriksnulstilling, der sletter alle dine data uden bekræftelse."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Slet telefonens data uden varsel ved at gendanne fabriksindstillinger"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Angiv enhedens globale proxy"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Angiv enhedens globale proxy, der skal bruges, mens politikken er aktiveret. Kun den første enhedsadministrator angiver den effektive globale proxy."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjem"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Arbejde"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Andre"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Tilpasset"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Tilpasset"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Hjem"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbejde"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Andre"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Indtast PIN-kode"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Indtast adgangskode for at låse op"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Indtast pinkode for at låse op"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Tip: Dobbeltklik for at zoome ind eller ud."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Autofuldfør denne formular"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"læs browserens oversigt og bogmærker"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillader, at programmet læser alle de webadresser, browseren har besøgt, og alle browserens bogmærker."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriv browserens oversigt og bogmærker"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Tillader, at et program ændrer browseroversigten eller bogmærker, der er gemt på din telefon. Ondsindede programmer kan bruge dette til at slette eller ændre din browsers data."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"angiv alarm i alarmprogram"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Tillader, at programmet angiver en alarm i et installeret alarmprogram. Nogle alarmprogrammer kan ikke implementere denne funktion."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Skift browsertilladelser for geografisk placering"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Giver et program tilladelse til at ændre browserens tilladelser for geografisk placering. Skadelige programmer kan bruge dette til at tillade, at placeringsoplysninger sendes til vilkårlige websteder."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ønsker du, at browseren skal huske denne adgangskode?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Tving til at lukke"</string>
     <string name="report" msgid="4060218260984795706">"Rapporter"</string>
     <string name="wait" msgid="7147118217226317732">"Vent"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Programmet er omdirigeret"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> kører nu."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> blev oprindeligt åbnet."</string>
     <string name="smv_application" msgid="295583804361236288">"Programmet <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) har overtrådt sin egen StrictMode-politik."</string>
     <string name="smv_process" msgid="5120397012047462446">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> har overtrådt sin egen StrictMode-politik."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> er i gang"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Vis alle"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-masselagring"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB er tilsluttet"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Du har forbundet din telefon til din computer via USB. Vælg knappen nedenfor, hvis du ønsker at kopiere filer mellem din computer og din Androids SD-kort."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Du har forbundet din telefon til din computer via USB. Vælg knappen nedenfor, hvis du vil kopiere filer mellem din computer og din Androids USB-lager."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Du har forbundet din telefon til din computer via USB. Vælg knappen nedenfor, hvis du ønsker at kopiere filer mellem din computer og din Androids SD-kort."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Slå USB-lagringen til"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Der opstod et problem med at bruge dit SD-kort til USB-lagring."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Der opstod et problem med at bruge USB-lager til USB-masselager."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Der opstod et problem med at bruge dit SD-kort til USB-masselager."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB er tilsluttet"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Vælg for at kopiere filer til/fra din computer."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Slå USB-lagringen fra"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Vælg for at slå USB-lagring fra."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-lager i brug"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Sørg for, at du har demonteret (\"udskubbet\") din Androids SD-kort fra computeren, før du slår USB-lagring fra."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Sørg for, at du har demonteret (\"udskubbet\") din Androids USB-lager fra computeren, før du slår USB-lager fra."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Sørg for, at du har demonteret (\"udskubbet\") din Androids SD-kort fra computeren, før du slår USB-lagring fra."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Slå USB-lagring fra"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Der opstod et problem med at slå USB-lagringen fra. Sørg for, at du har demonteret USB-værten, og prøv så igen."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Slå USB-lagring til"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du slår USB-lagring til, vil nogle af de programmer, som du bruger, stoppe, og de kan være utilgængelige, indtil du slår USB-lagring til igen."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-handlingen mislykkedes"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formater SD-kort"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Er du sikker på, du ønsker at formatere SD-kortet? Alle data på kortet mistes."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formater USB-lager"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formater SD-kort"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vil du formatere USB-lager og slette alle filer, som er gemt der? Handlingen kan ikke fortrydes!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Er du sikker på, du ønsker at formatere SD-kortet? Alle data på kortet mistes."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formater"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-fejlretning er tilsluttet"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Vælg for at deaktivere USB-fejlretning."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Forbereder SD-kortet"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Forbereder USB-lager"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Forbereder SD-kortet"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Kontrollerer for fejl."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Tomt SD-kort"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"SD-kortet er tomt eller har et ikke understøttet filsystem."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Beskadiget SD-kort"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"SD-kortet er beskadiget. Du bliver muligvis nødt til at formatere det igen."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"SD-kortet blev fjernet uventet"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Demonter SD-kortet inden fjernelse for at undgå tab af data."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"SD-kortet kan fjernes sikkert"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Du kan nu fjerne SD-kortet."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"SD-kortet er fjernet"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"SD-kortet er fjernet. Indsæt et nyt."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Tomt USB-lager"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tomt SD-kort"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB-lager er tomt eller har et ikke-understøttet filsystem."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-kortet er tomt eller har et ikke understøttet filsystem."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Beskadiget USB-lager"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Beskadiget SD-kort"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB-lager er beskadiget. Du skal muligvis formatere det igen."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD-kortet er beskadiget. Du bliver muligvis nødt til at formatere det igen."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-lager blev fjernet uventet"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-kortet blev fjernet uventet"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Demonter USB-lager inden fjernelse for at undgå tab af data."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Demonter SD-kortet inden fjernelse for at undgå tab af data."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Sikkert at fjerne USB-lager"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD-kortet kan fjernes sikkert"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Det er nu sikkert at fjerne USB-lager."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Du kan nu fjerne SD-kortet."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Fjernet USB-lager"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD-kortet er fjernet"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB-lager er fjernet. Indsæt nyt medie."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-kortet er fjernet. Indsæt et nyt."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Der blev ikke fundet nogen matchende aktiviteter"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"opdater brugerstatistikker for komponenter"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Tillader ændring af indsamlede brugerstatistikker for komponenter. Ikke til brug til normale programmer."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 match"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> af <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Demonterer USB-lager..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Demonterer SD-kort..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Sletter USB-lager..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Sletter SD-kort..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"USB-lager kunne ikke slettes."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"SD-kortet kunne ikke slettes."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD-kortet blev fjernet, før det blev demonteret."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB-lager bliver kontrolleret."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SD-kortet bliver kontrolleret."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD-kortet er fjernet."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB-lager er i øjeblikket i brug af en computer."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SD-kortet er i øjeblikket i brug af en computer."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Eksternt medie i ukendt tilstand."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index bbe8de9..6aeb1cd 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -122,8 +122,8 @@
     <string name="httpErrorFileNotFound" msgid="5588380756326017105">"Die angeforderte Datei wurde nicht gefunden."</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Es werden zurzeit zu viele Anfragen verarbeitet. Versuchen Sie es später erneut."</string>
     <string name="notification_title" msgid="1259940370369187045">"Fehler bei Anmeldung für <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
-    <string name="contentServiceSync" msgid="8353523060269335667">"Synchronisieren"</string>
-    <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronisieren"</string>
+    <string name="contentServiceSync" msgid="8353523060269335667">"Synchronisierung"</string>
+    <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronisierung"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Zu viele <xliff:g id="CONTENT_TYPE">%s</xliff:g> gelöscht."</string>
     <string name="low_memory" msgid="6632412458436461203">"Telefonspeicher ist voll! Löschen Sie Dateien, um Speicherplatz freizugeben."</string>
     <string name="me" msgid="6545696007631404292">"Eigene"</string>
@@ -135,17 +135,19 @@
     <string name="power_off" msgid="4266614107412865048">"Ausschalten"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Wird heruntergefahren..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Ihr Telefon wird heruntergefahren."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Zuletzt verwendet"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Keine zuletzt verwendeten Anwendungen"</string>
     <string name="global_actions" msgid="2406416831541615258">"Telefonoptionen"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Display-Sperre"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Ausschalten"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Lautlos"</string>
-    <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Ton ist AUS"</string>
+    <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Ton ist aus"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Ton ist AN"</string>
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flugmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flugmodus ist AN"</string>
-    <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist AUS"</string>
+    <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist aus"</string>
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Kostenpflichtige Dienste"</string>
@@ -154,7 +156,7 @@
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Lesen und schreiben Sie Ihre SMS, E-Mails und anderen Nachrichten."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Ihre persönlichen Informationen"</string>
     <string name="permgroupdesc_personalInfo" msgid="5488050357388806068">"Direkter Zugriff auf die Kontakte und den Kalender Ihres Telefons."</string>
-    <string name="permgrouplab_location" msgid="635149742436692049">"Ihr Standort"</string>
+    <string name="permgrouplab_location" msgid="635149742436692049">"Ihren Standort"</string>
     <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>
@@ -169,11 +171,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Entwickler-Tools"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funktionen nur für Anwendungsentwickler vorgesehen."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Speicher"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Greift auf die SD-Karte zu."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Zugriff auf USB-Speicher"</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Greift auf die SD-Karte zu."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Statusleiste deaktivieren oder ändern"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Ermöglicht der Anwendung, die Statusanzeige zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"Statusleiste"</string>
-    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Die Anwendung wird damit in der Statusleiste angezeigt."</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Ermöglicht der Anwendung, zur Statusleiste zu werden."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"Statusleiste ein-/ausblenden"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Ermöglicht der Anwendung, die Statusleiste ein- oder auszublenden."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"Abgehende Anrufe abfangen"</string>
@@ -183,7 +186,7 @@
     <string name="permlab_receiveMms" msgid="8894700916188083287">"MMS empfangen"</string>
     <string name="permdesc_receiveMms" msgid="4563346832000174373">"Ermöglicht der Anwendung, MMS-Mitteilungen zu empfangen und zu verarbeiten. Schädliche Anwendungen können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"Kurznachrichten senden"</string>
-    <string name="permdesc_sendSms" msgid="1946540351763502120">"Ermöglicht Anwendungen das Senden von SMS-Nachrichten. Bei schädlichen Anwendungen können Kosten entstehen, wenn diese Nachrichten ohne Ihre Zustimmung versenden."</string>
+    <string name="permdesc_sendSms" msgid="1946540351763502120">"Ermöglicht der Anwendung das Senden von SMS-Nachrichten. Bei schädlichen Anwendungen können Kosten entstehen, wenn diese Nachrichten ohne Ihre Zustimmung versenden."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"SMS oder MMS lesen"</string>
     <string name="permdesc_readSms" msgid="3002170087197294591">"Ermöglicht einer Anwendung, auf Ihrem Telefon oder Ihrer SIM-Karte gespeicherte Kurznachrichten zu lesen. Schädliche Anwendungen lesen so möglicherweise Ihre  vertraulichen Nachrichten."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"SMS oder MMS bearbeiten"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Ermöglicht einer Anwendung, Telefonspeicher durch das Löschen von Dateien im Cache-Verzeichnis der Anwendung freizugeben. Der Zugriff beschränkt sich in der Regel auf Systemprozesse."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Anwendungsressourcen verschieben"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Ermöglicht einer Anwendung, Anwendungsressourcen von interne auf externe Medien zu verschieben und umgekehrt."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"Lesen vertraulicher Protokolldaten"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Ermöglicht einer Anwendung, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Telefon durchgeführten Aktionen eingesehen werden. Diese können persönliche oder geheime Daten enthalten."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"Lese-/Schreibberechtigung für zu Diagnosegruppe gehörige Elemente"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Ermöglicht einer Anwendung, alle Elemente in der Diagnosegruppe zu lesen und zu bearbeiten, etwa Dateien in \"/dev\". Dies könnte eine potenzielle Gefährdung für die Stabilität und Sicherheit des Systems darstellen und sollte NUR für Hardware-spezifische Diagnosen des Herstellers oder Netzbetreibers verwendet werden."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"Anwendungskomponenten aktivieren oder deaktivieren"</string>
@@ -313,31 +314,31 @@
     <string name="permlab_recordAudio" msgid="3876049771427466323">"Audio aufnehmen"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Ermöglicht der Anwendung, auf den Pfad für Audioaufzeichnungen zuzugreifen."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"Bilder und Videos aufnehmen"</string>
-    <string name="permdesc_camera" msgid="6004878235852154239">"Ermöglicht der Anwendung, Fotos und Videos mit der Kamera aufzunehmen. So kann die Anwendung jederzeit Bilder zusammentragen, die von der Kamera erfasst werden."</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Ermöglicht der Anwendung, Fotos und Videos mit der Kamera aufzunehmen. So kann die Anwendung jederzeit Bilder aus dem Sichtfeld der Kamera erfassen."</string>
     <string name="permlab_brick" msgid="8337817093326370537">"Telefon dauerhaft deaktivieren."</string>
     <string name="permdesc_brick" msgid="5569526552607599221">"Ermöglicht der Anwendung, das gesamte Telefon dauerhaft zu deaktivieren. Dies birgt hohe Risiken."</string>
     <string name="permlab_reboot" msgid="2898560872462638242">"Neustart des Telefons erzwingen"</string>
     <string name="permdesc_reboot" msgid="7914933292815491782">"Ermöglicht der Anwendung, einen Neustart des Telefons zu erzwingen."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"Dateisysteme bereitstellen oder Bereitstellung aufheben"</string>
-    <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Ermöglicht der Anwendung, Dateisysteme für austauschbare Speicherplätze bereitzustellen oder die Bereitstellung aufzuheben."</string>
+    <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Ermöglicht der Anwendung, Dateisysteme für austauschbare Datenträger bereitzustellen oder die Bereitstellung aufzuheben."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"Externen Speicher formatieren"</string>
-    <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Erlaubt der Anwendung, austauschbaren Speicher zu formatieren."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"Informationen zum sicheren Speicher abrufen"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Ermöglicht der Anwendung, Informationen zum sicheren Speicher abzurufen."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"Sicheren Speicher erstellen"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Ermöglicht der Anwendung, einen sicheren Speicher zu erstellen."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"Sicheren Speicher entfernen"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Ermöglicht der Anwendung, den sicheren Speicher zu entfernen."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"Sicheren Speicher bereitstellen/trennen"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Ermöglicht der Anwendung, sicheren Speicher bereitzustellen bzw. zu trennen."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"Sicheren Speicher umbenennen"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Ermöglicht der Anwendung, den sicheren Speicher umzubenennen."</string>
+    <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Ermöglicht der Anwendung, austauschbare Datenträger zu formatieren."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"Informationen zum internen Speicher abrufen"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Ermöglicht der Anwendung, Informationen zum internen Speicher abzurufen."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"Internen Speicher erstellen"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Ermöglicht der Anwendung, einen internen Speicher zu erstellen."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"Internen Speicher vernichten"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Ermöglicht der Anwendung, den internen Speicher zu vernichten."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"Internen Speicher bereitstellen/trennen"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Ermöglicht der Anwendung, internen Speicher bereitzustellen bzw. zu trennen."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"Internen Speicher umbenennen"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Ermöglicht der Anwendung, den internen Speicher umzubenennen."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"Vibrationsalarm steuern"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Ermöglicht der Anwendung, den Vibrationsalarm zu steuern."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"Lichtanzeige steuern"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Ermöglicht der Anwendung, die Lichtanzeige zu steuern."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"auf USB-Geräte zugreifen"</string>
-    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Die Anwendung erhält Zugriff auf USB-Geräte."</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Ermöglicht der Anwendung den Zugriff auf USB-Geräte."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"Hardware testen"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Ermöglicht einer Anwendung, verschiedene Peripherie-Geräte zu Hardware-Testzwecken zu steuern."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"Telefonnummern direkt anrufen"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Ermöglicht einer Anwendung, das lokale Bluetooth-Telefon zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth-Verbindungen herstellen"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Ermöglicht einer Anwendung, die Konfiguration des lokalen Bluetooth-Telefons einzusehen und Verbindungen mit Partnergeräten herzustellen und zu akzeptieren."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"Nahfeldkommunikation steuern"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Ermöglicht einer Anwendung die Kommunikation mit Tags für die Nahfeldkommunikation, Karten und Readern."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"Tastensperre deaktivieren"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Ermöglicht einer Anwendung, die Tastensperre sowie den damit verbundenen Passwortschutz zu deaktivieren. So wird die Tastensperre vom Telefon deaktiviert, wenn ein Anruf eingeht, und nach Beendigung des Anrufs wieder aktiviert."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Synchronisierungseinstellungen lesen"</string>
@@ -417,63 +420,66 @@
     <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"abonnierte Feeds schreiben"</string>
     <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"Ermöglicht einer Anwendung, Änderungen an den kürzlich synchronisierten Feeds vorzunehmen. Schädliche Anwendungen könnten so Ihre synchronisierten Feeds ändern."</string>
     <string name="permlab_readDictionary" msgid="432535716804748781">"nutzerdefiniertes Wörterbuch lesen"</string>
-    <string name="permdesc_readDictionary" msgid="1082972603576360690">"Erlaubt einer Anwendung, alle privaten Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat."</string>
+    <string name="permdesc_readDictionary" msgid="1082972603576360690">"Ermöglicht einer Anwendung, alle privaten Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"in nutzerdefiniertes Wörterbuch schreiben"</string>
-    <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Erlaubt einer Anwendung, neue Wörter in das Wörterbuch des Nutzers zu schreiben."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"SD-Karten-Inhalt ändern/löschen"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Ermöglicht einer Anwendung, auf die SD-Karte zu schreiben"</string>
+    <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Ermöglicht einer Anwendung, Ihrem Wörterbuch neue Einträge hinzuzufügen."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"USB-Speicherinh. ändern/lösch."</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"SD-Karten-Inhalt ändern/löschen"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ermöglicht der Anwendung Schreiben in USB-Speicher"</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Ermöglicht einer Anwendung, auf die SD-Karte zu schreiben"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"Zugriff auf das Cache-Dateisystem"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Gewährt einer Anwendung Lese- und Schreibzugriff auf das Cache-Dateisystem."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Passwort beschränken"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Beschränken der erlaubten Passworttypen"</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Anmeldeversuche überwachen"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Fehlgeschlagene Versuche·zum Anmelden/Durchführen einer Aktion überwachen"</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Passwort zurücksetzen"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Festlegen eines neuen Werts für Ihr Passwort, sodass der Administrator es Ihnen vor dem Anmelden übermitteln muss."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Sperren erzwingen"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Steuerung der Gerätesperre; erfordert die erneute Passworteingabe"</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"Internetanrufe tätigen/annehmen"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Ermöglicht einer Anwendung die Verwendung des SIP-Dienstes zum Tätigen/Annehmen von Internetanrufen."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Zulässige Länge und Zeichen für Passwörter zum Entsperren des Displays festlegen"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays überwachen und Telefon sperren oder alle Daten auf dem Telefon löschen, wenn zu häufig ein falsches Passwort eingegeben wird"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Passwort zum Entsperren des Displays ändern"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Passwort zum Entsperren des Displays ändern"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Display sperren"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Steuern Sie, wie und wann das Display gesperrt wird."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Alle Daten löschen"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Zurücksetzen auf die Werkseinstellungen. Dabei werden alle Ihre Daten ohne Nachfrage gelöscht."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Auf Werkseinstellungen zurücksetzen und Daten auf dem Telefon ohne Warnung löschen"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Den globalen Proxy des Geräts festlegen"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Den globalen Proxy des Geräts zur Verwendung während der Aktivierung der Richtlinie festlegen. Nur der erste Geräteadministrator kann den gültigen globalen Proxy festlegen."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Privat"</item>
     <item msgid="869923650527136615">"Mobil"</item>
-    <item msgid="7897544654242874543">"Arbeit"</item>
-    <item msgid="1103601433382158155">"Fax (Arbeit)"</item>
+    <item msgid="7897544654242874543">"Geschäftlich"</item>
+    <item msgid="1103601433382158155">"Fax (geschäftl.)"</item>
     <item msgid="1735177144948329370">"Fax (privat)"</item>
     <item msgid="603878674477207394">"Pager"</item>
-    <item msgid="1650824275177931637">"Andere"</item>
+    <item msgid="1650824275177931637">"Sonstige"</item>
     <item msgid="9192514806975898961">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="emailAddressTypes">
     <item msgid="8073994352956129127">"Privat"</item>
-    <item msgid="7084237356602625604">"Arbeit"</item>
-    <item msgid="1112044410659011023">"Andere"</item>
+    <item msgid="7084237356602625604">"Geschäftlich"</item>
+    <item msgid="1112044410659011023">"Sonstige"</item>
     <item msgid="2374913952870110618">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="postalAddressTypes">
     <item msgid="6880257626740047286">"Privat"</item>
-    <item msgid="5629153956045109251">"Arbeit"</item>
-    <item msgid="4966604264500343469">"Andere"</item>
+    <item msgid="5629153956045109251">"Geschäftlich"</item>
+    <item msgid="4966604264500343469">"Sonstige"</item>
     <item msgid="4932682847595299369">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="imAddressTypes">
     <item msgid="1738585194601476694">"Privat"</item>
-    <item msgid="1359644565647383708">"Arbeit"</item>
+    <item msgid="1359644565647383708">"Geschäftlich"</item>
     <item msgid="7868549401053615677">"Andere"</item>
     <item msgid="3145118944639869809">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="organizationTypes">
-    <item msgid="7546335612189115615">"Arbeit"</item>
-    <item msgid="4378074129049520373">"Andere"</item>
+    <item msgid="7546335612189115615">"Geschäftlich"</item>
+    <item msgid="4378074129049520373">"Sonstige"</item>
     <item msgid="3455047468583965104">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="imProtocols">
     <item msgid="8595261363518459565">"AIM"</item>
     <item msgid="7390473628275490700">"Windows Live"</item>
-    <item msgid="7882877134931458217">"Yahoo"</item>
+    <item msgid="7882877134931458217">"Yahoo!"</item>
     <item msgid="5035376313200585242">"Skype"</item>
     <item msgid="7532363178459444943">"QQ"</item>
     <item msgid="3713441034299660749">"Google Talk"</item>
@@ -483,11 +489,11 @@
     <string name="phoneTypeCustom" msgid="1644738059053355820">"Benutzerdefiniert"</string>
     <string name="phoneTypeHome" msgid="2570923463033985887">"Privat"</string>
     <string name="phoneTypeMobile" msgid="6501463557754751037">"Mobil"</string>
-    <string name="phoneTypeWork" msgid="8863939667059911633">"Arbeit"</string>
-    <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Fax (Beruflich)"</string>
+    <string name="phoneTypeWork" msgid="8863939667059911633">"Geschäftlich"</string>
+    <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Fax (geschäftl.)"</string>
     <string name="phoneTypeFaxHome" msgid="2067265972322971467">"Fax (privat)"</string>
     <string name="phoneTypePager" msgid="7582359955394921732">"Pager"</string>
-    <string name="phoneTypeOther" msgid="1544425847868765990">"Andere"</string>
+    <string name="phoneTypeOther" msgid="1544425847868765990">"Sonstige"</string>
     <string name="phoneTypeCallback" msgid="2712175203065678206">"Rückruf"</string>
     <string name="phoneTypeCar" msgid="8738360689616716982">"Auto"</string>
     <string name="phoneTypeCompanyMain" msgid="540434356461478916">"Firma (Hauptnummer)"</string>
@@ -497,8 +503,8 @@
     <string name="phoneTypeRadio" msgid="4093738079908667513">"Radio"</string>
     <string name="phoneTypeTelex" msgid="3367879952476250512">"Telex"</string>
     <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY/TDD"</string>
-    <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Handy (geschäftlich)"</string>
-    <string name="phoneTypeWorkPager" msgid="649938731231157056">"Pager (beruflich)"</string>
+    <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Handy (geschäftl.)"</string>
+    <string name="phoneTypeWorkPager" msgid="649938731231157056">"Pager (geschäftl.)"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Zweite Nummer"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Geburtstag"</string>
@@ -506,38 +512,34 @@
     <string name="eventTypeOther" msgid="5834288791948564594">"Termin"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Benutzerdefiniert"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Privat"</string>
-    <string name="emailTypeWork" msgid="3548058059601149973">"Beruflich"</string>
-    <string name="emailTypeOther" msgid="2923008695272639549">"Andere"</string>
+    <string name="emailTypeWork" msgid="3548058059601149973">"Geschäftlich"</string>
+    <string name="emailTypeOther" msgid="2923008695272639549">"Sonstige"</string>
     <string name="emailTypeMobile" msgid="119919005321166205">"Mobil"</string>
     <string name="postalTypeCustom" msgid="8903206903060479902">"Benutzerdefiniert"</string>
     <string name="postalTypeHome" msgid="8165756977184483097">"Privat"</string>
-    <string name="postalTypeWork" msgid="5268172772387694495">"Beruflich"</string>
-    <string name="postalTypeOther" msgid="2726111966623584341">"Andere"</string>
+    <string name="postalTypeWork" msgid="5268172772387694495">"Geschäftlich"</string>
+    <string name="postalTypeOther" msgid="2726111966623584341">"Sonstige"</string>
     <string name="imTypeCustom" msgid="2074028755527826046">"Benutzerdefiniert"</string>
     <string name="imTypeHome" msgid="6241181032954263892">"Privat"</string>
-    <string name="imTypeWork" msgid="1371489290242433090">"Beruflich"</string>
-    <string name="imTypeOther" msgid="5377007495735915478">"Andere"</string>
+    <string name="imTypeWork" msgid="1371489290242433090">"Geschäftlich"</string>
+    <string name="imTypeOther" msgid="5377007495735915478">"Sonstige"</string>
     <string name="imProtocolCustom" msgid="6919453836618749992">"Benutzerdefiniert"</string>
     <string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
     <string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
-    <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</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">"Beruflich"</string>
-    <string name="orgTypeOther" msgid="3951781131570124082">"Andere"</string>
+    <string name="orgTypeWork" msgid="29268870505363872">"Geschäftlich"</string>
+    <string name="orgTypeOther" msgid="3951781131570124082">"Sonstige"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Benutzerdefiniert"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Benutzerdefiniert"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Privat"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Geschäftlich"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Sonstige"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN-Code eingeben"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Passwort zum Entsperren eingeben"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"PIN zum Entsperren eingeben"</string>
@@ -552,8 +554,8 @@
     <string name="lockscreen_emergency_call" msgid="5347633784401285225">"Notruf"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Zurück zum Anruf"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Korrekt!"</string>
-    <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Tut uns leid. Versuchen Sie es noch einmal."</string>
-    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Tut uns leid. Versuchen Sie es noch einmal."</string>
+    <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Bitte versuchen Sie es erneut."</string>
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Bitte versuchen Sie es erneut."</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Wird geladen (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Aufgeladen"</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Tipp: Zum Heranzoomen und Vergrößern zweimal tippen"</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Dieses Formular automatisch ausfüllen"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Ermöglicht einer Anwendung, den auf Ihrem Telefon gespeicherten Browserverlauf und die Lesezeichen zu ändern. Schädliche Anwendungen können so Ihre Browserdaten löschen oder ändern."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"Alarm im Wecker festlegen"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Ermöglicht dieser Anwendung, einen Alarm mithilfe eines installierten Weckers festzulegen. Einige Weckeranwendungen verfügen möglicherweise nicht über diese Funktion."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Geolokalisierungsberechtigungen des Browsers ändern"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Ermöglicht einer Anwendung, die Geolokalisierungsberechtigungen des Browsers zu ändern. Schädliche Anwendungen können dies nutzen, um das Senden von Standortinformationen an willkürliche Websites zuzulassen."</string>
     <string name="save_password_message" msgid="767344687139195790">"Möchten Sie, dass der Browser dieses Passwort speichert?"</string>
@@ -725,7 +728,7 @@
     <string name="inputMethod" msgid="1653630062304567879">"Eingabemethode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Textaktionen"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Geringer Speicher"</string>
-    <string name="low_internal_storage_view_text" msgid="635106544616378836">"Kaum noch freier Telefonspeicher verfügbar."</string>
+    <string name="low_internal_storage_view_text" msgid="635106544616378836">"Kaum noch Telefonspeicher frei."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Abbrechen"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -733,10 +736,10 @@
     <string name="dialog_alert_title" msgid="2049658708609043103">"Achtung"</string>
     <string name="loading" msgid="1760724998928255250">"Wird geladen..."</string>
     <string name="capital_on" msgid="1544682755514494298">"EIN"</string>
-    <string name="capital_off" msgid="6815870386972805832">"AUS"</string>
+    <string name="capital_off" msgid="6815870386972805832">"Aus"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Aktion durchführen mit"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Standardmäßig für diese Aktion verwenden."</string>
-    <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Löschen Sie die Standardeinstellungen unter \"Starteinstellungen &gt; Anwendungen &gt; Anwendungen verwalten\"."</string>
+    <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Standardeinstellung zurücksetzen unter \"Einstellungen &gt; Anwendungen &gt; Anwendungen verwalten\"."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Aktion auswählen"</string>
     <string name="noApplications" msgid="1691104391758345586">"Diese Aktion kann von keiner Anwendung ausgeführt werden."</string>
     <string name="aerr_title" msgid="653922989522758100">"Tut uns leid!"</string>
@@ -750,22 +753,19 @@
     <string name="force_close" msgid="3653416315450806396">"Schließen erzwingen"</string>
     <string name="report" msgid="4060218260984795706">"Bericht"</string>
     <string name="wait" msgid="7147118217226317732">"Warten"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Anwendung umgeleitet"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> wird jetzt ausgeführt."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> wurde ursprünglich gestartet."</string>
     <string name="smv_application" msgid="295583804361236288">"Die Anwendung <xliff:g id="APPLICATION">%1$s</xliff:g> (Prozess <xliff:g id="PROCESS">%2$s</xliff:g>) hat gegen ihre selbsterzwungene StrictMode-Richtlinie verstoßen."</string>
     <string name="smv_process" msgid="5120397012047462446">"Der Prozess <xliff:g id="PROCESS">%1$s</xliff:g> hat gegen seine selbsterzwungene StrictMode-Richtlinie verstoßen."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> läuft"</string>
     <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Auswählen zum Wechseln in die Anwendung"</string>
     <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Anwendung wechseln?"</string>
-    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Eine andere Anwendung wird bereits ausgeführt und muss vor dem Start einer neuen Anwendung beendet werden."</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Es läuft gerade eine andere Anwendung, die vor dem Start einer neuen beendet werden muss."</string>
     <string name="old_app_action" msgid="493129172238566282">"Zu <xliff:g id="OLD_APP">%1$s</xliff:g> zurückkehren"</string>
-    <string name="old_app_description" msgid="942967900237208466">"Starten Sie die neue Anwendung nicht."</string>
+    <string name="old_app_description" msgid="942967900237208466">"Die neue Anwendung nicht starten."</string>
     <string name="new_app_action" msgid="5472756926945440706">"<xliff:g id="OLD_APP">%1$s</xliff:g> starten"</string>
-    <string name="new_app_description" msgid="6830398339826789493">"Beenden Sie die Anwendung ohne zu speichern."</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Anwendung beenden, ohne zu speichern."</string>
     <string name="sendText" msgid="5132506121645618310">"Aktion für Text auswählen"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Klingeltonlautstärke"</string>
     <string name="volume_music" msgid="5421651157138628171">"Medienlautstärke"</string>
@@ -802,42 +802,58 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Alle anzeigen"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-Massenspeicher"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-Verbindung"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Sie haben Ihr Telefon über USB mit Ihrem Computer verbunden. Wählen Sie die Schaltfläche unten aus, wenn Sie Dateien auf Ihren Computer oder die SD-Karte Ihres Android-Geräts kopieren möchten."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Sie haben Ihr Telefon über USB mit Ihrem Computer verbunden. Wählen Sie die Schaltfläche unten aus, wenn Sie Dateien von Ihrem Computer in den USB-Speicher Ihres Android-Geräts und umgekehrt kopieren möchten."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Sie haben Ihr Telefon über USB mit Ihrem Computer verbunden. Wählen Sie die Schaltfläche unten aus, wenn Sie Dateien auf Ihren Computer oder die SD-Karte Ihres Android-Geräts kopieren möchten."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USB-Speicher aktivieren"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Bei der Verwendung Ihrer SD-Karte als USB-Speicher ist ein Problem aufgetreten."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Bei der Verwendung Ihres USB-Speichers als USB-Massenspeicher ist ein Problem aufgetreten."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Bei der Verwendung Ihrer SD-Karte als USB-Massenspeicher ist ein Problem aufgetreten."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB-Verbindung"</string>
-    <string name="usb_storage_notification_message" msgid="7380082404288219341">"Zum Kopieren von Dateien zu/von Ihrem Computer."</string>
+    <string name="usb_storage_notification_message" msgid="7380082404288219341">"Zum Kopieren von Dateien zum/vom Computer"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB-Speicher deaktivieren"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Auswählen, um USB-Speicher zu deaktivieren."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-Speicher in Verwendung"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Stellen Sie vor dem Deaktivieren des USB-Speichers sicher, dass Sie Ihre Android-SD-Karte von Ihrem Computer getrennt (\"ausgeworfen\") haben."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Stellen Sie vor dem Deaktivieren des USB-Speichers sicher, dass Sie den Android-USB-Speicher von Ihrem Computer getrennt (\"ausgeworfen\") haben."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Stellen Sie vor dem Deaktivieren des USB-Speichers sicher, dass Sie Ihre Android-SD-Karte von Ihrem Computer getrennt (\"ausgeworfen\") haben."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB-Speicher deaktivieren"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Beim Deaktivieren des USB-Speichers ist ein Problem aufgetreten. Überprüfen Sie, ob Sie den USB-Host getrennt haben, und versuchen Sie es erneut."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"USB-Speicher aktivieren"</string>
-    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Wenn Sie den USB-Speicher aktivieren, werden einige von Ihnen verwendete Anwendungen angehalten und sind möglicherweise nicht verfügbar, bis Sie den USB-Speicher wieder deaktivieren."</string>
+    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Wenn Sie den USB-Speicher aktivieren, werden einige von Ihnen verwendeten Anwendungen angehalten und sind möglicherweise nicht verfügbar, bis Sie den USB-Speicher wieder deaktivieren."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-Vorgang fehlgeschlagen"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"SD-Karte formatieren"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Möchten Sie die SD-Karte wirklich formatieren? Alle Daten auf Ihrer Karte gehen dann verloren."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB-Sp. formatieren"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-Karte formatieren"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB-Speicher formatieren und alle darin befindlichen Dateien löschen? Diese Aktion kann nicht rückgängig gemacht werden!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Möchten Sie die SD-Karte wirklich formatieren? Alle Daten auf Ihrer Karte gehen dann verloren."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-Debugging verbunden"</string>
-    <string name="adb_active_notification_message" msgid="8470296818270110396">"Zum Deaktivieren des USB-Debugging auswählen"</string>
+    <string name="adb_active_notification_message" msgid="8470296818270110396">"Auswählen, um USB-Debugging zu deaktivieren."</string>
     <string name="select_input_method" msgid="6865512749462072765">"Eingabemethode auswählen"</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>"Kandidaten"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"SD-Karte wird vorbereitet"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"USB-Speicher wird vorbereitet."</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD-Karte wird vorbereitet"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Suche nach Fehlern"</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"SD-Karte leer"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"SD-Karte ist leer oder verfügt über ein nicht unterstütztes Dateisystem."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Beschädigte SD-Karte"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"Die SD-Karte ist beschädigt. Sie müssen Ihre Karte eventuell neu formatieren."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"SD-Karte unerwartet entfernt"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"SD-Karte vor dem Entnehmen trennen, um Datenverlust zu vermeiden."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"SD-Karte\nkann entfernt werden."</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Die SD-Karte kann entfernt werden."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"SD-Karte entfernt"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"SD-Karte entfernt. Legen Sie eine neue ein."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"USB-Speicher leer"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"SD-Karte leer"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB-Speicher ist leer oder verfügt über ein nicht unterstütztes Dateisystem."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-Karte ist leer oder verfügt über ein nicht unterstütztes Dateisystem."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB-Speicher beschädigt"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Beschädigte SD-Karte"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB-Speicher ist beschädigt. Sie müssen ihn neu formatieren."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Die SD-Karte ist beschädigt. Sie müssen Ihre Karte eventuell neu formatieren."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-Speicher unerw. entfernt"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-Karte unerwartet entfernt"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Trennen Sie den USB-Speicher vor dem Entfernen, um Datenverlust zu vermeiden."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"SD-Karte vor dem Entnehmen trennen, um Datenverlust zu vermeiden."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB-Speicher kann entf. werden"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD-Karte kann entfernt werden."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Der USB-Speicher kann entfernt werden."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Die SD-Karte kann entfernt werden."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB-Speicher entfernt"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD-Karte entfernt"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB-Speicher entfernt. Neuen Datenträger einlegen"</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-Karte entfernt. Legen Sie eine neue ein."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Keine passenden Aktivitäten gefunden"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"Nutzungsstatistik der Komponente aktualisieren"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Ermöglicht die Änderung von gesammelten Nutzungsstatistiken der Komponente. Nicht für normale Anwendungen vorgesehen."</string>
@@ -886,10 +902,29 @@
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Weitere Informationen über die Mobildatennutzung durch Berühren aufrufen"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Mobildatenlimit überschritten"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Weitere Informationen über die Mobildatennutzung durch Berühren aufrufen"</string>
-    <string name="no_matches" msgid="8129421908915840737">"Keine Übereinstimmungen"</string>
+    <string name="no_matches" msgid="8129421908915840737">"Keine Treffer"</string>
     <string name="find_on_page" msgid="1946799233822820384">"Auf Seite suchen"</string>
   <plurals name="matches_found">
-    <item quantity="one" msgid="8167147081136579439">"1 Übereinstimmung"</item>
+    <item quantity="one" msgid="8167147081136579439">"1 Treffer"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> von <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"USB-Speicher wird getrennt..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"SD-Karte wird getrennt..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"USB-Speicher wird gelöscht..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"SD-Karteninhalt wird gelöscht..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"USB-Speicher konnte nicht gelöscht werden."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"SD-Karte konnte nicht gelöscht werden."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD-Karte wurde vor dem Trennvorgang entfernt."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Der USB-Speicher wird derzeit überprüft."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Die SD-Karte wird derzeit überprüft."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Die SD-Karte wurde entfernt."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Der USB-Speicher wird derzeit von einem Computer verwendet."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Die SD-Karte wird derzeit von einem Computer verwendet."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Unbekannter Status des externen Speichermediums"</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index e2a01f4..c87a7cd 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Απενεργοποίηση"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Απενεργοποίηση..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Το τηλέφωνό σας θα απενεργοποιηθεί."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Πρόσφατα"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Δεν υπάρχουν πρόσφατες εφαρμογές."</string>
     <string name="global_actions" msgid="2406416831541615258">"Επιλογές τηλεφώνου"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Εργαλεία ανάπτυξης"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Δυνατότητες που είναι απαραίτητες μόνο σε προγραμματιστές εφαρμογών."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Αποθηκευτικός χώρος"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Πρόσβαση στην κάρτα SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Πρόσβαση στον χώρο αποθ. USB."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Πρόσβαση στην κάρτα SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"απενεργοποίηση ή τροποποίηση γραμμής κατάστασης"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"γραμμή κατάστασης"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Επιτρέπει σε μια εφαρμογή να αυξήσει τον ελεύθερο χώρο αποθήκευσης του τηλεφώνου διαγράφοντας αρχεία από τον κατάλογο προσωρινής μνήμης της εφαρμογής. Η πρόσβαση είναι συνήθως πολύ περιορισμένη στη διαδικασία συστήματος."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Μετακίνηση πόρων εφαρμογής"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Επιτρέπει σε μια εφαρμογή τη μετακίνηση πόρων εφαρμογής από ένα εσωτερικό σε ένα εξωτερικό μέσο και αντίστροφα."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"ανάγνωση ευαίσθητων δεδομένων αρχείου καταγραφής"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Επιτρέπει σε μια εφαρμογή την ανάγνωση των αρχείων καταγραφής του συστήματος. Έτσι, μπορεί να ανακαλύψει γενικές πληροφορίες σχετικά με τις δραστηριότητές σας στο τηλέφωνο, συμπεριλαμβάνοντας πιθανώς και προσωπικές ή ιδιωτικές πληροφορίες."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"ανάγνωση/εγγραφή σε πόρους που ανήκουν στο διαγνωστικό"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Επιτρέπει σε μια εφαρμογή την ανάγνωση και την εγγραφή σε πόρο που ανήκει στην ομάδα διαγνωστικού (π.χ. αρχεία στον κατάλογο /dev). Αυτό ενδέχεται να επηρεάσει την σταθερότητα και την ασφάλεια του συστήματος. Θα πρέπει να χρησιμοποιείται ΜΟΝΟ για διαγνωστικά υλικού του κατασκευαστή ή του χειριστή."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"ενεργοποίηση ή απενεργοποίηση στοιχείων εφαρμογής"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Επιτρέπει στην εφαρμογή την προσάρτηση και αποπροσάρτηση συστημάτων αρχείων για αφαιρούμενο αποθηκευτικό χώρο."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"διαμόρφωση εξωτερικού αποθηκευτικού χώρου"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Επιτρέπει στην εφαρμογή τη διαμόρφωση αφαιρούμενου αποθηκευτικού χώρου."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"λήψη πληροφοριών στον ασφαλή χώρο αποθήκευσης"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Επιτρέπει στην εφαρμογή τη λήψη πληροφοριών στον ασφαλή χώρο αποθήκευσης."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"δημιουργία ασφαλούς χώρου αποθήκευσης"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Επιτρέπει στην εφαρμογή τη δημιουργία ασφαλούς χώρου αποθήκευσης."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"καταστροφή ασφαλούς χώρου αποθήκευσης"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Επιτρέπει στην εφαρμογή την καταστροφή του ασφαλούς χώρου αποθήκευσης."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"σύνδεση / αποσύνδεση ασφαλούς χώρου αποθήκευσης"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Επιτρέπει στην εφαρμογή τη σύνδεση / αποσύνδεση του ασφαλούς χώρου αποθήκευσης."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"μετονομασία ασφαλούς χώρου αποθήκευσης"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Επιτρέπει στην εφαρμογή τη μετονομασία του ασφαλούς χώρου αποθήκευσης."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"λήψη πληροφοριών στον εσωτερικό χώρο αποθήκευσης"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Επιτρέπει στην εφαρμογή τη λήψη πληροφοριών στον εσωτερικό χώρο αποθήκευσης."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"δημιουργία εσωτερικού αποθηκευτικού χώρου"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Επιτρέπει στην εφαρμογή τη δημιουργία εσωτερικού χώρου αποθήκευσης."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"καταστροφή εσωτερικού χώρου αποθήκευσης"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Επιτρέπει στην εφαρμογή την καταστροφή του εσωτερικού χώρου αποθήκευσης."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"προσάρτηση / αποπροσάρτηση εσωτερικού αποθηκευτικού χώρου"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Επιτρέπει στην εφαρμογή την προσάρτηση / αποπροσάρτηση του εσωτερικού χώρου αποθήκευσης."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"μετονομασία εσωτερικού αποθηκευτικού χώρου"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Επιτρέπει στην εφαρμογή τη μετονομασία του εσωτερικού χώρου αποθήκευσης."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"έλεγχος δόνησης"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Επιτρέπει στην εφαρμογή τον έλεγχο του δονητή."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"έλεγχος φακού"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Επιτρέπει σε μια εφαρμογή τη διαμόρφωση του τοπικού τηλεφώνου Bluetooth και την ανακάλυψη και σύζευξη με απομακρυσμένες συσκευές."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"δημιουργία συνδέσεων Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Επιτρέπει σε μια εφαρμογή να προβάλει τη διαμόρφωση του τοπικού τηλεφώνου Bluetooth και επίσης να πραγματοποιεί και να αποδέχεται συνδέσεις με συζευγμένες συσκευές."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"έλεγχος Επικοινωνίας κοντινού πεδίου (Near Field Communication)"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Επιτρέπει σε μια εφαρμογή την επικοινωνία με ετικέτες, τις κάρτες και τους αναγνώστες της Επικοινωνίας κοντινού πεδίου (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"απενεργοποίηση κλειδώματος πληκτρολογίου"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Επιτρέπει σε μια εφαρμογή την απενεργοποίηση του κλειδώματος πληκτρολογίου και άλλης σχετικής ασφάλειας με κωδικό πρόσβασης. Για παράδειγμα, η απενεργοποίηση του κλειδώματος πληκτρολογίου όταν λαμβάνεται εισερχόμενη τηλεφωνική κλήση και η επανενεργοποίηση του κλειδώματος πληκτρολογίου όταν η κλήση τερματιστεί."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ανάγνωση ρυθμίσεων συγχρονισμού"</string>
@@ -420,22 +423,25 @@
     <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="permdesc_sdcardWrite" msgid="6643963204976471878">"Επιτρέπει στην εφαρμογή την εγγραφή στην κάρτα SD."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"τροπ./διαγρ. περ. απ. χώρ. USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"τροποποίηση/διαγραφή περιεχομένων κάρτας SD"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Επ. εγγρ. εφ. σε απ. χώρο USB"</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Επιτρέπει στην εφαρμογή την εγγραφή στην κάρτα SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"πρόσβαση στο σύστημα αρχείων προσωρινής μνήμης"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Επιτρέπει σε μια εφαρμογή την ανάγνωση και την εγγραφή του συστήματος αρχείων προσωρινής μνήμης."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Περιορισμός επιλογών κωδικού πρόσβασης"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Περιορισμός των τύπων κωδικού πρόσβασης που επιτρέπεται να χρησιμοποιείτε."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Παρακολούθηση προσπαθειών σύνδεσης"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Παρακολούθηση αποτυχημένων προσπαθειών σύνδεσης με τη συσκευή, για την εκτέλεσης κάποιας ενέργειας."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Επαναφορά κωδικού πρόσβασης"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Εφαρμογή του κωδικού πρόσβασής σας σε μια νέα τιμή, με την προϋπόθεση ότι σας παρέχεται από τον διαχειριστή για να μπορείτε να συνδεθείτε."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Εφαρμογή κλειδώματος"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Ελέγχει πότε κλειδώνει η συσκευή, απαιτώντας κωδικό πρόσβασης για επανείσοδο."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"πραγματοποίηση/λήψη κλήσεων μέσω Διαδικτύου"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Επιτρέπει σε μια εφαρμογή τη χρήση της υπηρεσίας SIP για την πραγματοποίηση/λήψη κλήσεων μέσω Διαδικτύου."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Έλεγχος του μεγέθους και των χαρακτήρων που επιτρέπονται στους κωδικούς πρόσβασης ξεκλειδώματος οθόνης"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Παρακολούθηση του αριθμού των εσφαλμένων κωδικών πρόσβασης που έχουν εισαχθεί κατά το ξεκλείδωμα της οθόνης και κλείδωμα του τηλεφώνου ή διαγραφή όλων των δεδομένων του τηλεφώνου σε περίπτωση που έχουν εισαχθεί πάρα πολλοί εσφαλμένοι κωδικοί πρόσβασης"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Αλλαγή κωδικού πρόσβασης ξεκλειδώματος οθόνης"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Αλλαγή κωδικού πρόσβασης ξεκλειδώματος οθόνης"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Κλείδωμα οθόνης"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Έλεγχος του τρόπου και του χρόνου κλειδώματος της οθόνης"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Διαγραφή όλων των δεδομένων"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Πραγματοποιείται επαναφορά εργοστασιακών ρυθμίσεων, με τη διαγραφή όλων των δεδομένων σας χωρίς επιβεβαίωση."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Διαγραφή των δεδομένων του τηλεφώνου χωρίς προειδοποίηση με επαναφορά των εργοστασιακών δεδομένων"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Ρύθμιση του γενικού διακομιστή μεσολάβησης της συσκευής"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Ορίστε τη χρήση του γενικού διακομιστή μεσολάβησης της συσκευής όταν είναι ενεργοποιημένη η πολιτική. Μόνο ο διαχειριστής της πρώτης συσκευής ορίζει τον ισχύοντα γενικό διακομιστή μεσολάβησης."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Οικία"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Εργασία"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Άλλο"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Προσαρμοσμένο"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Προσαρμοσμένο"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Αρχική σελίδα"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Εργασία"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Άλλο"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Πληκτρολογήστε τον κωδικό αριθμό PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Εισαγάγετε τον κωδικό πρόσβασης για ξεκλείδωμα"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Εισαγάγετε το PIN για ξεκλείδωμα"</string>
@@ -570,7 +572,7 @@
     <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_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Καταχωρίσατε εσφαλμένα τον κωδικό πρόσβασης <xliff:g id="NUMBER_0">%d</xliff:g> φορές. "\n\n"Προσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%d</xliff:g> δευτερόλεπτα."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Καταχωρίσατε εσφαλμένα το PIN σας<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> \nδευτερόλεπτα."</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>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Προσπαθήστε ξανά σε <xliff:g id="NUMBER">%d</xliff:g> δευτερόλεπτα."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Ξεχάσατε το μοτίβο;"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Ξεκλείδωμα λογαριασμού"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Συμβουλή: διπλό άγγιγμα για μεγέθυνση και σμίκρυνση."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Να γίνει αυτόματη συμπλήρωση αυτής της φόρμας"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ανάγνωση ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Επιτρέπει στην εφαρμογή την ανάγνωση όλων των διευθύνσεων URL που το πρόγραμμα περιήγησης έχει επισκεφθεί και όλων των σελιδοδεικτών του προγράμματος περιήγησης."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"εγγραφή ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Επιτρέπει σε μια εφαρμογή να τροποποιήσει το ιστορικό ή τους σελιδοδείκτες του προγράμματος περιήγησης που βρίσκονται αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν τα δεδομένα του προγράμματος περιήγησης."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"ρύθμιση ειδοποίησης σε ξυπνητήρι"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Επιτρέπει στην εφαρμογή να ρυθμίσει μια ειδοποίηση σε μια εγκατεστημένη εφαρμογή ξυπνητηριού. Κάποιες εφαρμογές ξυπνητηριού ενδέχεται να μην περιλαμβάνουν αυτή τη λειτουργία."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Τροποποίηση δικαιωμάτων γεωγραφικής θέσης προγράμματος περιήγησης"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Επιτρέπει σε μια εφαρμογή την τροποποίηση των δικαιωμάτων γεωγραφικής θέσης του προγράμματος περιήγησης. Οι κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να επιτρέψουν την αποστολή στοιχείων τοποθεσίας σε αυθαίρετους ιστότοπους."</string>
     <string name="save_password_message" msgid="767344687139195790">"Θέλετε το πρόγραμμα περιήγησης να διατηρήσει αυτόν τον κωδικό πρόσβασης;"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Αναγκαστικό κλείσιμο"</string>
     <string name="report" msgid="4060218260984795706">"Αναφορά"</string>
     <string name="wait" msgid="7147118217226317732">"Αναμονή"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Ανακατεύθυνση εφαρμογής"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> εκτελείται τώρα."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Έγινε εκκίνηση πρώτα της εφαρμογής <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="smv_application" msgid="295583804361236288">"Η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> (διεργασία <xliff:g id="PROCESS">%2$s</xliff:g>) παραβίασε την αυτοεπιβαλόμενη πολιτική StrictMode."</string>
     <string name="smv_process" msgid="5120397012047462446">"Η διεργασία <xliff:g id="PROCESS">%1$s</xliff:g> παραβίασε την αυτοεπιβαλόμενη πολιτική StrictMode."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> εκτελείται"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Εμφάνιση όλων"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Μαζική αποθήκευση USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Το USB είναι συνδεδεμένο"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Συνδέσατε το τηλέφωνό σας στον υπολογιστή μέσω USB. Επιλέξτε το παρακάτω κουμπί αν θέλετε να αντιγράψετε αρχεία μεταξύ του υπολογιστή και της κάρτας SD του Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Συνδέσατε το τηλέφωνό σας στον υπολογιστή μέσω USB. Επιλέξτε το παρακάτω κουμπί αν θέλετε να αντιγράψετε αρχεία μεταξύ του υπολογιστή και του χώρου αποθήκευσης USB του Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Συνδέσατε το τηλέφωνό σας στον υπολογιστή μέσω USB. Επιλέξτε το παρακάτω κουμπί αν θέλετε να αντιγράψετε αρχεία μεταξύ του υπολογιστή και της κάρτας SD του Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Ενεργοποίηση αποθηκευτικού χώρου USB"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Παρουσιάστηκε ένα πρόβλημα στη χρήση της κάρτας SD ως αποθηκευτικό χώρο USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Παρουσιάστηκε ένα πρόβλημα στη χρήση του αποθηκευτικού χώρου USB ως χώρο USB μαζικής αποθήκευσης."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Παρουσιάστηκε ένα πρόβλημα στη χρήση της κάρτας SD ως χώρο USB μαζικής αποθήκευσης."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Το USB είναι συνδεδεμένο"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Επιλέξτε για αντιγραφή προς/από τον υπολογιστή σας."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Απενεργοποίηση αποθηκευτικού χώρου USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Επιλογή για απενεργοποίηση αποθηκευτικού χώρου USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Χώρος αποθήκευσης USB σε χρήση"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Προτού απενεργοποιήσετε το χώρο αποθήκευσης USB, βεβαιωθείτε ότι έχετε αποσυνδέσει (“αφαιρέσει”) την κάρτα SD του Android από τον υπολογιστή σας."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Προτού απενεργοποιήσετε τον χώρο αποθήκευσης USB, βεβαιωθείτε ότι έχετε αποπροσαρτήσει (\"αφαιρέσει\") τον αποθηκευτικό χώρο USB του Android από τον υπολογιστή σας."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Προτού απενεργοποιήσετε το χώρο αποθήκευσης USB, βεβαιωθείτε ότι έχετε αποσυνδέσει (“αφαιρέσει”) την κάρτα SD του Android από τον υπολογιστή σας."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Απενεργοποίηση χώρου αποθήκευσης USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Παρουσιάστηκε πρόβλημα κατά την απενεργοποίηση του αποθηκευτικού χώρου USB. Βεβαιωθείτε ότι έχετε αφαιρέσει την υποδοχή USB και προσπαθήστε ξανά."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Ενεργοποίηση αποθηκευτικού χώρου USB"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Εάν ενεργοποιήσετε τον αποθηκευτικό χώρο USB, ορισμένες από τις εφαρμογές που χρησιμοποιείτε θα σταματήσουν και ενδέχεται να μην είναι διαθέσιμες μέχρι να απενεργοποιήσετε τον αποθηκευτικό χώρο USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Απέτυχε η λειτουργία USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"ΟΚ"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Διαμόρφωση κάρτας SD"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Είστε βέβαιοι ότι θέλετε να διαμορφώσετε την κάρτα SD; Όλα τα δεδομένα στην κάρτα σας θα χαθούν."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Διαγρ. απ. χώρου USB"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Διαμόρφωση κάρτας SD"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Να γίνει διαγραφή του αποθηκευτικού χώρου USB, η οποία θα διαγράψει όλα τα αρχεία που έχετε αποθηκεύσει εκεί; Η ενέργεια είναι μη αναστρέψιμη!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Είστε βέβαιοι ότι θέλετε να διαμορφώσετε την κάρτα SD; Όλα τα δεδομένα στην κάρτα σας θα χαθούν."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Διαμόρφωση"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Συνδέθηκε ο εντοπισμός σφαλμάτων USB"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Επιλογή για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"υποψήφιοι"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Προετοιμασία κάρτας SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Προετοιμασία αποθ. χώρου USB"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Προετοιμασία κάρτας SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Έλεγχος για σφάλματα."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Κενή κάρτα SD"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"Η κάρτα SD είναι κενή ή έχει μη υποστηριζόμενο σύστημα αρχείων."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Κατεστραμμένη κάρτα SD"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"Η κάρτα SD παρουσιάζει βλάβη. Ενδεχομένως θα πρέπει να προβείτε σε διαμόρφωσή της."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"Μη αναμενόμενη αφαίρεση κάρτας SD"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Αποπροσαρτήστε την κάρτα SD πριν την αφαιρέσετε για την αποφυγή απώλειας δεδομένων."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"Η κάρτα SD μπορεί να αφαιρεθεί με ασφάλεια"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Μπορείτε να αφαιρέσετε με ασφάλεια της κάρτα SD."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Η κάρτα SD αφαιρέθηκε"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"Αφαιρέθηκε η κάρτα SD. Τοποθετήστε μια νέα κάρτα."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Κενός αποθηκευτικός χώρος USB"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Κενή κάρτα SD"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Ο αποθηκευτικός χώρος USB είναι κενός ή έχει κάποιο σύστημα αρχείων το οποίο δεν υποστηρίζεται."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Η κάρτα SD είναι κενή ή έχει μη υποστηριζόμενο σύστημα αρχείων."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Βλάβη αποθηκευτικού χώρου USB"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Κατεστραμμένη κάρτα SD"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Ο αποθηκευτικός χώρος USB παρουσιάζει βλάβη. Ενδεχομένως θα πρέπει να προβείτε σε διαμόρφωσή του."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Η κάρτα SD παρουσιάζει βλάβη. Ενδεχομένως θα πρέπει να προβείτε σε διαμόρφωσή της."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Μη αναμ. κατάργ. απ. χώρου USB"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Μη αναμενόμενη αφαίρεση κάρτας SD"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Αποπροσαρτήστε τον αποθηκευτικό χώρο USB πριν τον αφαιρέσετε για την αποφυγή απώλειας δεδομένων."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Αποπροσαρτήστε την κάρτα SD πριν την αφαιρέσετε για την αποφυγή απώλειας δεδομένων."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Ασφαλ. κατάργ. αποθ. χώρου USB"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Η κάρτα SD μπορεί να αφαιρεθεί με ασφάλεια"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Μπορείτε να καταργήσετε τον αποθηκευτικό χώρο USB με ασφάλεια."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Μπορείτε να αφαιρέσετε με ασφάλεια της κάρτα SD."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Ο αποθ. χώρος USB καταργήθηκε"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Η κάρτα SD αφαιρέθηκε"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Ο αποθηκευτικός χώρος USB καταργήθηκε. Εισαγάγετε νέα πολυμέσα."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Αφαιρέθηκε η κάρτα SD. Τοποθετήστε μια νέα κάρτα."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Δεν βρέθηκαν δραστηριότητες που να αντιστοιχούν"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"ενημέρωση στατιστικών χρήσης στοιχείου"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Επιτρέπει την τροποποίηση στατιστικών χρήσης στοιχείων που έχουν συλλεχθεί. Δεν πρέπει να χρησιμοποιείται από κανονικές εφαρμογές."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 αποτέλεσμα"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> από <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Αποπροσάρτηση αποθηκευτικού χώρου USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Αποπροσάρτηση κάρτας SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Διαγραφή αποθηκευτικού χώρου USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Διαγραφή κάρτας SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Αποτυχία διαγραφής αποθηκευτικού χώρου USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Αποτυχία διαγραφής κάρτας SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Η κάρτα SD καταργήθηκε πριν την αποπροσάρτησή της."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Αυτή τη στιγμή γίνεται έλεγχος του αποθηκευτικού χώρου USB."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Γίνεται έλεγχος της κάρτας SD."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Η κάρτα SD έχει αφαιρεθεί."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Αυτή τη στιγμή ο αποθηκευτικός χώρος USB χρησιμοποιείται από κάποιον υπολογιστή."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Αυτή τη στιγμή η κάρτα SD χρησιμοποιείται από κάποιον υπολογιστή."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Το εξωτερικό μέσο είναι σε άγνωστη κατάσταση."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index fe27b95..1610659 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -135,6 +135,7 @@
     <string name="power_off" msgid="4266614107412865048">"Apagar"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Apagando…"</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Tu teléfono se apagará."</string>
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">" Me gusta  Para:"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Reciente"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"No hay aplicaciones recientes."</string>
     <string name="global_actions" msgid="2406416831541615258">"Opciones de teléfono"</string>
@@ -169,7 +170,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Herramientas de desarrollo"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Las funciones sólo son necesarias para los desarrolladores de aplicaciones."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Espacio de almacenamiento"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Acceder a la tarjeta SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Acceder al almacenamiento USB."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Acceder a la tarjeta SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra de estado"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Admite que la aplicación desactive la barra de estado, o agregue y elimine íconos del sistema."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"barra de estado"</string>
@@ -266,10 +268,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Admite una aplicación que libera espacio de almacenamiento en el teléfono al eliminar archivos del directorio de memoria caché de la aplicación. En general, el acceso es muy restringido para el proceso del sistema."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Mover recursos de la aplicación"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Permite a una aplicación mover recursos de aplicación de medios internos a externos y viceversa."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"lee los datos confidenciales del registro"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Admite una aplicación que lee diversos archivos de registro del sistema. Esto te permite descubrir información general acerca de lo que haces con el teléfono, y puede potencialmente incluir información personal o privada."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"leer y escribir a recursos dentro del grupo de diagnóstico"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Admite una aplicación que lee y escribe a cualquier recurso dentro del grupo de diagnóstico; por ejemplo, archivos con /dev. Esto puede afectar potencialmente la estabilidad y la seguridad del sistema. Debe utilizarlo SÓLO el fabricante o el operador en los diagnósticos específicos del hardware."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"activar o desactivar componentes de la aplicación"</string>
@@ -322,16 +322,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Admite que la aplicación monte y desmonte filesystems para obtener almacenamiento extraíble."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"espacio de almacenamiento externo del formato"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Admite que la aplicación formatee el espacio de almacenamiento extraíble."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"obtener información sobre el almacenamiento seguro"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Permite que una aplicación obtenga información en el almacenamiento seguro."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"crear almacenamiento seguro"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Permite que la aplicación cree un almacenamiento seguro."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"destruir el almacenamiento seguro"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Permite que una aplicación destruya el almacenamiento seguro."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"montar o desmontar almacenamiento seguro"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Permite que una aplicación monte o desmonte el almacenamiento seguro."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"cambie el nombre del almacenamiento seguro"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Permite que una aplicación cambie el nombre de un almacenamiento seguro."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"obtener información sobre el almacenamiento interno"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Permite que la aplicación obtenga información sobre el almacenamiento interno."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"crear almacenamiento interno"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Permite que la aplicación cree un almacenamiento interno."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"destruir almacenamiento interno"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permite que la aplicación destruya el almacenamiento interno."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"montar o desmontar almacenamiento interno"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Permite que la aplicación monte o desmonte el almacenamiento interno."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"cambiar el nombre del almacenamiento interno"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permite que la aplicación cambie el nombre de un almacenamiento interno."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"vibrador de control"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Admite que la aplicación controle el vibrador."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controlar linterna"</string>
@@ -404,6 +404,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Admite una aplicación que configura el teléfono Bluetooth local y descubre y se vincula con dispositivos remotos."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"crear conexiones de Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Admite una aplicación que ve la configuración del teléfono Bluetooth local, y realiza y acepta conexiones con dispositivos vinculados."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"controlar la Transmisión de datos en proximidad"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Permite que una aplicación se comunique con etiquetas, tarjetas y lectores de Transmisión de datos en proximidad (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"desactivar el bloqueo"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Admite una aplicación que desactiva el bloqueo y cualquier seguridad con contraseña relacionada. Un ejemplo legítimo de esto es el bloqueo desactivado por el teléfono cuando recibe una llamada telefónica entrante, y luego la reactivación del bloqueo cuando finaliza la llamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
@@ -420,22 +422,25 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Admite una aplicación para leer palabras, nombres y frases privadas que posiblemente el usuario haya almacenado en el diccionario del usuario."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"escribir al diccionario definido por el usuario"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Admite una aplicación que escribe palabras nuevas en el diccionario del usuario."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"modificar/suprimir el contenido de la tarjeta SD"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Admite que una aplicación escriba en la tarjeta SD."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modificar o suprimir el contenido del almacenamiento USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/suprimir el contenido de la tarjeta SD"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Permite que una aplicación escriba en el almacenamiento USB."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Admite que una aplicación escriba en la tarjeta SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"Acceder al sistema de archivos caché"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que una aplicación lea y escriba el sistema de archivos caché."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Limitar la contraseña"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Restringe los tipos de contraseñas que puedes utilizar."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Observar los intentos de acceso"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Intentos fallidos del control para acceder al dispositivo para realizar alguna acción."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Restablecer contraseña"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Forzar un nuevo valor para tu contraseña, el administrador deberá enviártelo antes de poder acceder."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Provocar el bloqueo"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Controlar cuando se bloquee el dispositivo, requiere que vuelvas a ingresar tu contraseña."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"realizar o recibir llamadas por Internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Permite que una aplicación utilice el servicio SIP para realizar o recibir llamadas por Internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlar la longitud y los caracteres permitidos en las contraseñas para desbloquear la pantalla"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Supervisa el número de contraseñas incorrectas ingresadas al desbloquear la pantalla, y bloquee el teléfono o elimine todos los datos del teléfono si se ingresan demasiadas contraseñas incorrectas."</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Cambiar la contraseña para desbloquear la pantalla"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Cambiar la contraseña para desbloquear la pantalla"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloquear la pantalla"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Controlar cómo y cuándo se bloquea la pantalla"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Borrar todos los datos"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Realizar un reestablecimiento de fábrica y borrar todos tus datos sin ninguna confirmación."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Borrar los datos del teléfono sin advertencias al restablecer la configuración original"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Configura el proxy global de dispositivo"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Configuración del proxy global de dispositivo que se utilizará mientras se habilita la política. Sólo la primera administración de dispositivo configura el proxy global efectivo."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
@@ -530,14 +535,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Trabajo"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Otro"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Personalizado"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalizado"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Página principal"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Trabajo"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Otro"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ingresar el código de PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Ingresar la contraseña para desbloquear"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Ingresa el PIN para desbloquear"</string>
@@ -598,12 +599,13 @@
     <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>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Autocompletar este formulario"</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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Permite a una aplicación modificar el historial y los marcadores del navegador almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar tus datos."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"configurar alarma en reloj alarma"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que la aplicación configure una alarma en una aplicación instalada de reloj alarma. Es posible que algunas aplicaciones de reloj alarma no implementen esta función."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar los permisos de ubicación geográfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que una aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones maliciosas pueden utilizarlos para permitir el envío de información sobre la ubicación a sitos web de forma arbitraria."</string>
     <string name="save_password_message" msgid="767344687139195790">"¿Quieres recordar esta contraseña en el navegador?"</string>
@@ -721,7 +723,7 @@
     <string name="paste" msgid="5629880836805036433">"Pegar"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Copiar URL"</string>
     <string name="selectTextMode" msgid="6738556348861347240">"Seleccionar texto..."</string>
-    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selección de texto "</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selección de texto"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Poco espacio de almacenamiento"</string>
@@ -747,15 +749,12 @@
     <string name="anr_activity_process" msgid="5420826626009561014">"La actividad <xliff:g id="ACTIVITY">%1$s</xliff:g> (en proceso <xliff:g id="PROCESS">%2$s</xliff:g>) no responde."</string>
     <string name="anr_application_process" msgid="4185842666452210193">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (en proceso <xliff:g id="PROCESS">%2$s</xliff:g>) no responde."</string>
     <string name="anr_process" msgid="1246866008169975783">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> no responde."</string>
-    <string name="force_close" msgid="3653416315450806396">"Provocar acercamiento"</string>
+    <string name="force_close" msgid="3653416315450806396">"Forzar cierre"</string>
     <string name="report" msgid="4060218260984795706">"Notificar"</string>
     <string name="wait" msgid="7147118217226317732">"Espera"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Se redirigió la aplicación"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> se está ejecutando ahora."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> se inició originalmente."</string>
     <string name="smv_application" msgid="295583804361236288">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) ha violado su política StrictMode autoimpuesta."</string>
     <string name="smv_process" msgid="5120397012047462446">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha violado su política StrictMode autoimpuesta."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> Correr"</string>
@@ -802,23 +801,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar todos"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Almacenamiento masivo USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"conectado al USB"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Has conectado tu teléfono a tu computadora mediante USB. Selecciona el botón a continuación si deseas copiar los archivos entre tu computadora y la tarjeta SD de Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Has conectado tu teléfono a tu computadora mediante USB. Selecciona el botón a continuación si deseas copiar los archivos entre tu computadora y el almacenamiento USB de Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Has conectado tu teléfono a tu computadora mediante USB. Selecciona el botón a continuación si deseas copiar los archivos entre tu computadora y la tarjeta SD de Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activar el almacenamiento USB"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Hay un problema para utilizar tu tarjeta SD en el almacenamiento USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Hay un problema para utilizar el almacenamiento USB en el almacenamiento masivo USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Hay un problema para utilizar tu tarjeta SD en el almacenamiento masivo USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"conectado al USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Seleccionar para copiar archivos desde o hacia tu computadora."</string>
-    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Apagar el almacenamiento USB"</string>
+    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Desactivar el almacenamiento USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Seleccionar para desactivar el almacenamiento USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Almacenamiento USB en uso"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado (\"expulsado\") la tarjeta SD de Android de tu computadora."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado (\"expulsado\") el almacenamiento USB de Android de tu computadora."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado (\"expulsado\") la tarjeta SD de Android de tu computadora."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Desactivar el almacenamiento USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Se ha producido un problema al desactivar el almacenamiento USB. Asegúrate de haber desmontado el host USB, luego vuelve a intentarlo."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Activar el almacenamiento USB"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activas el almacenamiento USB, algunas aplicaciones que estás usando se detendrán y es posible que no estén disponibles hasta que desactives el almacenamiento USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Error en el funcionamiento del USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formatear tarjeta SD"</string>
-    <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_title" product="nosdcard" msgid="7980995592595097841">"Formatear almacenamiento USB"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatear tarjeta SD"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"¿Deseas formatear el almacenamiento USB y borrar todos los archivos almacenados aquí? ¡Esta acción no se puede cambiar!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de tu tarjeta."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formato"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración de USB conectada"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Seleccionar para desactivar la depuración de USB."</string>
@@ -826,18 +830,29 @@
     <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>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Preparación de la tarjeta SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Preparando almacenamiento USB"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Preparación de la tarjeta SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Verificando errores"</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Tarjeta SD vacía"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"Tarjeta SD en blanco o el sistema de archivos no es compatible."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Tarjeta SD dañada"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"Tarjeta SD dañada. Es posible que debas reformatearla."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"Tarjeta SD extraída de forma imprevista"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Desmontar la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"Tarjeta SD fácil de extraer"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Puedes eliminar la tarjeta SD sin riesgos."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Tarjeta SD extraída"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"Tarjeta SD eliminada. Inserta una nueva."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Almacenamiento USB en blanco"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tarjeta SD vacía"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Almacenamiento USB en blanco o sistema de archivos no compatible."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Tarjeta SD en blanco o el sistema de archivos no es compatible."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Almacenamiento USB dañado"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Tarjeta SD dañada"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Almacenamiento USB dañado. Es posible que debas reformatearlo."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Tarjeta SD dañada. Es posible que debas reformatearla."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Almacenamiento USB extraído inesperadamente"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Tarjeta SD extraída de forma imprevista"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desmontar el almacenamiento USB antes de extraerlo para evitar la pérdida de datos."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desmontar la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Es seguro extraer el almacenamiento USB"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Tarjeta SD fácil de extraer"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Puedes extraer de forma segura el almacenamiento USB."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puedes eliminar la tarjeta SD sin riesgos."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Almacenamiento USB extraído"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Tarjeta SD extraída"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Almacenamiento USB eliminado. Insertar nuevos medios."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Tarjeta SD eliminada. Inserta una nueva."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"No se encontraron actividades coincidentes"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar la estadística de uso de los componentes"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Permite la modificación de estadísticas recopiladas sobre el uso de componentes. Las aplicaciones normales no deben utilizarlo."</string>
@@ -884,7 +899,7 @@
     <string name="skip_button_label" msgid="1275362299471631819">"Omitir"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Amplia utilización de datos móviles"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Toca para obtener más información acerca de la utilización de datos móviles."</string>
-    <string name="throttled_notification_title" msgid="6269541897729781332">"Límite de datos móviles excedido "</string>
+    <string name="throttled_notification_title" msgid="6269541897729781332">"Límite de datos móviles excedido"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Toca para obtener más información acerca de la utilización de datos móviles."</string>
     <string name="no_matches" msgid="8129421908915840737">"Sin coincidencias"</string>
     <string name="find_on_page" msgid="1946799233822820384">"Buscar en la página"</string>
@@ -892,4 +907,22 @@
     <item quantity="one" msgid="8167147081136579439">"1 coincidencia"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Finalizado"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Desmontando almacenamiento USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Desmontando la tarjeta SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Borrando almacenamiento USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Borrando tarjeta SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"No pudo borrar el almacenamiento USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"No pudo borrar la tarjeta SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Se ha extraído la tarjeta SD antes de ser desmontada."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Se está verificando el almacenamiento USB en este momento."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Se está verificando la tarjeta SD en este momento."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Se ha extraído la tarjeta SD."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Una computadora está utilizando el almacenamiento USB en este momento."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Una computadora está utilizando la tarjeta SD en este momento."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Medios externos en estado desconocido."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 10ecaca..d4163fd 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Apagar"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Apagando..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"El teléfono se apagará."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Reciente"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"No hay aplicaciones recientes"</string>
     <string name="global_actions" msgid="2406416831541615258">"Opciones del teléfono"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Herramientas de desarrollo"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funciones necesarias solo para desarrolladores de aplicaciones"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Almacenamiento"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Acceder a la tarjeta SD"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Acceso a almacenamiento USB"</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Acceder a la tarjeta SD"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"inhabilitar o modificar la barra de estado"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permite que las aplicaciones inhabiliten la barra de estado, o añadan y eliminen iconos del sistema."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"barra de estado"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Permite que una aplicación libere espacio de almacenamiento en el teléfono mediante la eliminación de archivos en el directorio de caché de la aplicación. El acceso al proceso del sistema suele estar muy restringido."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Mover recursos de aplicaciones"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Permite que una aplicación mueva los recursos de aplicaciones de un medio interno a otro externo y viceversa."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"leer datos de registro personales"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Permite que una aplicación lea distintos archivos de registro del sistema. Con este permiso, la aplicación puede ver información general sobre las acciones que realizas con el teléfono, que puede incluir datos personales o privados."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"leer/escribir en los recursos propiedad del grupo de diagnóstico"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Permite que una aplicación lea y escriba en cualquier recurso propiedad del grupo de diagnóstico como, por ejemplo, archivos in/dev. Este permiso podría afectar a la seguridad y estabilidad del sistema. SÓLO se debe utilizar para diagnósticos específicos de hardware realizados por el fabricante o el operador."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"habilitar o inhabilitar componentes de la aplicación"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Permite que las aplicaciones activen y desactiven sistemas de archivos para un almacenamiento extraíble."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatear almacenamiento externo"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Permite a la aplicación formatear un almacenamiento extraíble."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"obtener información sobre el almacenamiento seguro"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Permite que la aplicación obtenga información sobre el almacenamiento seguro."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"crear almacenamiento seguro"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Permite que la aplicación cree un almacenamiento seguro."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"destruir almacenamiento seguro"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Permite que la aplicación destruya el almacenamiento seguro."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"activar/desactivar almacenamiento seguro"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Permite que la aplicación active o desactive el almacenamiento seguro."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"cambiar nombre de almacenamiento seguro"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Permite que la aplicación cambie el nombre del almacenamiento seguro."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"obtener información sobre almacenamiento interno"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Permite que la aplicación obtenga información sobre el almacenamiento interno."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"crear almacenamiento interno"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Permite que la aplicación cree un almacenamiento interno."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"destruir almacenamiento interno"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permite que la aplicación destruya el almacenamiento interno."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"activar/desactivar almacenamiento interno"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Permite que la aplicación active o desactive el almacenamiento interno."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"cambiar el nombre del almacenamiento interno"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permite que la aplicación cambie el nombre del almacenamiento interno."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"controlar vibración"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permite que la aplicación controle la función de vibración."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controlar linterna"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Permite que una aplicación configure el teléfono Bluetooth local, y vea dispositivos remotos y sincronice el teléfono con ellos."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"crear conexiones de Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Permite que una aplicación vea la configuración del teléfono Bluetooth local, y cree y acepte conexiones con los dispositivos sincronizados."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"controlar Comunicación de campo cercano (NFC)"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Permite que la aplicación se comunique con lectores, tarjetas y etiquetas de Comunicación de campo cercano (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"inhabilitar bloqueo del teclado"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite que una aplicación inhabilite el bloqueo del teclado y cualquier protección con contraseña asociada. Un ejemplo legítimo de este permiso es la inhabilitación por parte del teléfono del bloqueo del teclado cuando recibe una llamada telefónica entrante y su posterior habilitación cuando finaliza la llamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
@@ -420,22 +423,25 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Permite a una aplicación leer cualquier frase, palabra o nombre privado que el usuario haya almacenado en su diccionario."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"escribir en el diccionario definido por el usuario"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permite a una aplicación escribir palabras nuevas en el diccionario de usuario."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"modificar/eliminar contenido de la tarjeta SD"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Permite que una aplicación escriba en la tarjeta SD."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modificar/borrar contenido USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/eliminar contenido de la tarjeta SD"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Permite escribir en USB"</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Permite que una aplicación escriba en la tarjeta SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"acceder al sistema de archivos almacenado en caché"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que una aplicación lea y escriba el sistema de archivos almacenado en caché."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Limitar opciones de contraseña"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Permite restringir los tipos de contraseñas que puede utilizar el usuario."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Controlar intentos de acceso"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Se ha producido un error al intentar controlar el acceso al dispositivo para realizar una acción."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Restablecer contraseña"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Permite forzar la contraseña para establecer un valor nuevo que el administrador deberá proporcionar al usuario para poder acceder."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Forzar bloqueo"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Permite controlar el momento de bloqueo del dispositivo solicitando al usuario que vuelva a introducir la contraseña."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"realizar/recibir llamadas por Internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Permite que una aplicación utilice el servicio SIP para realizar o recibir llamadas de Internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Control de la longitud y de los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Control del número de contraseñas incorrectas introducidas al desbloquear la pantalla, así como bloqueo del teléfono o borrado de todos los datos si se introducen demasiadas contraseñas incorrectas"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Modificación de contraseña de bloqueo de pantalla"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Modificación de contraseña de bloqueo de pantalla"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloqueo de pantalla"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Control de la forma en que se bloquea la pantalla y del momento en que se bloquea"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Borrar todos los datos"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Permite realizar un restablecimiento de fábrica eliminando todos los datos sin confirmación."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Borrado de los datos del teléfono sin avisar restableciendo datos de fábrica"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir el servidor proxy global"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Define el servidor proxy global que se debe utilizar mientras la política esté habilitada. Solo el primer administrador de dispositivos define el servidor proxy global efectivo."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Trabajo"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Otra"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Personalizada"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalizada"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Trabajo"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Otro"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduce el código PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Introducir contraseña para desbloquear"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Introducir PIN para desbloquear"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Sugerencia: toca dos veces para ampliar o reducir."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Autocompletar este formulario"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Permite que una aplicación modifique la información de los marcadores o del historial del navegador almacenada en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos del navegador."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"establecer alarma en un reloj"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite a la aplicación establecer una alarma en una aplicación de reloj instalada. Es posible que algunas aplicaciones de reloj no incluyan esta función."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar los permisos de ubicación geográfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que una aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones malintencionadas pueden utilizar este permiso para permitir el envío de información sobre la ubicación a sitios web arbitrarios."</string>
     <string name="save_password_message" msgid="767344687139195790">"¿Deseas que el navegador recuerde esta contraseña?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Forzar cierre"</string>
     <string name="report" msgid="4060218260984795706">"Informe"</string>
     <string name="wait" msgid="7147118217226317732">"Esperar"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Aplicación redireccionada"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> se está ejecutando."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Inicialmente, se inició la aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="smv_application" msgid="295583804361236288">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) ha infringido su política StrictMode autoaplicable."</string>
     <string name="smv_process" msgid="5120397012047462446">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha infringido su política StrictMode autoaplicable."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> en ejecución"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar todos"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Almacenamiento USB masivo"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Conectado por USB"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Has conectado el teléfono al equipo mediante USB. Selecciona el botón situado debajo si deseas copiar archivos entre el equipo y la tarjeta SD del teléfono con Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Has conectado el teléfono al equipo mediante USB. Selecciona el botón situado debajo si deseas copiar archivos entre el equipo y el almacenamiento USB del teléfono con Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Has conectado el teléfono al equipo mediante USB. Selecciona el botón situado debajo si deseas copiar archivos entre el equipo y la tarjeta SD del teléfono con Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activar almacenamiento USB"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Se ha producido un problema al intentar utilizar la tarjeta SD para el almacenamiento USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Se ha producido un problema al utilizar el almacenamiento USB para el almacenamiento masivo USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Se ha producido un problema al utilizar la tarjeta SD para el almacenamiento USB masivo."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Conectado por USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Para copiar archivos al/desde el equipo"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Desactivar almacenamiento USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Seleccionar para desactivar USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"El almacenamiento USB está en uso."</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado (\"retirado\") la tarjeta SD del teléfono con Android del equipo."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Antes de desactivar el almacenamiento USB, asegúrate de haber desactivado (\"extraído\") el almacenamiento USB del teléfono con Android del equipo."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado (\"retirado\") la tarjeta SD del teléfono con Android del equipo."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Desactivar almacenamiento USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Se ha producido un problema al desactivar el almacenamiento USB. Asegúrate de haber desactivado el host USB y, a continuación, vuelve a intentarlo."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Activar almacenamiento USB"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activas el almacenamiento USB, se detendrán algunas aplicaciones que estás utilizando y estas no estarán disponibles hasta que lo desactives."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"No se ha podido realizar la operación USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formatear tarjeta SD"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de la tarjeta."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatear USB"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatear tarjeta SD"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"¿Quieres formatear el USB y borrar todos los archivos? Esta acción no se puede deshacer."</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de la tarjeta."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formato"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Dispositivo de depuración USB conectado"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Seleccionar para inhabilitar la depuración USB"</string>
@@ -826,18 +831,29 @@
     <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>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Preparando tarjeta SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Preparando almacenamiento USB"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Preparando tarjeta SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Comprobando errores..."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Tarjeta SD vacía"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"La tarjeta SD está vacía o su sistema de archivos es incompatible."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Tarjeta SD dañada"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"La tarjeta SD está dañada. Es posible que sea necesario volver a formatearla."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"La tarjeta SD se ha extraído inesperadamente."</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Desactiva la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"Es seguro extraer la tarjeta SD."</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Puedes extraer la tarjeta SD de forma segura."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Tarjeta SD extraída"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"La tarjeta SD se ha extraído. Inserta una nueva."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Almacenamiento USB vacío"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tarjeta SD vacía"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Almacenamiento USB vacío o con sistema de archivos no admitido"</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"La tarjeta SD está vacía o su sistema de archivos es incompatible."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Almacenamiento USB dañado"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Tarjeta SD dañada"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Almacenamiento USB dañado. Es posible que haya que formatearlo."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"La tarjeta SD está dañada. Es posible que sea necesario volver a formatearla."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB extraído inesperadamente"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"La tarjeta SD se ha extraído inesperadamente."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desactiva el almacenamiento USB antes de extraerlo para evitar pérdidas de datos."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desactiva la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB extraíble forma segura"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Es seguro extraer la tarjeta SD."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Puedes extraer el almacenamiento USB de forma segura."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puedes extraer la tarjeta SD de forma segura."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Almacenamiento USB extraído"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Tarjeta SD extraída"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Almacenamiento USB extraído. Inserta un nuevo medio."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"La tarjeta SD se ha extraído. Inserta una nueva."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"No se ha encontrado ninguna actividad coincidente."</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar estadísticas de uso de componentes"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Permite la modificación de estadísticas recopiladas sobre el uso de componentes. No está destinado al uso por parte de aplicaciones normales."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"Una coincidencia"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Desactivando almacenamiento USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Desactivando tarjeta SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Borrando almacenamiento USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Borrando tarjeta SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Error al borrar almacenamiento USB"</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Error al borrar la tarjeta SD"</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"La tarjeta SD se ha extraído antes de desactivarla."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Se está comprobando el almacenamiento USB."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Se está comprobando la tarjeta SD."</string>
+    <string name="media_removed" msgid="7001526905057952097">"La tarjeta SD se ha extraído."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Un equipo está utilizando actualmente el almacenamiento USB."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Un equipo está utilizando actualmente la tarjeta SD."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Estado de medio externo desconocido"</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 2492a85..483ff5f1 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Éteindre"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Arrêt en cours..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Votre téléphone va s\'éteindre."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Récentes"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Aucune application récente"</string>
     <string name="global_actions" msgid="2406416831541615258">"Options du téléphone"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Outils de développement"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Ces fonctionnalités sont réservées aux développeurs d\'applications."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Stockage"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Accès à la carte SD"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accéder à la  mémoire de stockage USB"</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accès à la carte SD"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Désactivation ou modification de la barre d\'état"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permet à une application de désactiver la barre d\'état ou d\'ajouter/supprimer des icônes système."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"barre d\'état"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Permet à une application de libérer de l\'espace dans la mémoire du téléphone en supprimant des fichiers du répertoire du cache des applications. Cet accès est en général limité aux processus système."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Déplacer des ressources d\'application"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Autorise l\'application à déplacer des ressources d\'application d\'un support interne à un support externe et inversement."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"lire les données des journaux à caractère confidentiel"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Permet à une application de lire les différents fichiers journaux du système afin d\'obtenir des informations générales sur la façon dont vous utilisez votre téléphone (celles-ci peuvent éventuellement inclure des informations d\'ordre personnel ou privé)."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"Lecture/écriture dans les ressources appartenant aux diagnostics"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Permet à une application de lire et d\'éditer toute ressource appartenant au groupe de diagnostics (par exemple, les fichiers in/dev). Ceci peut affecter la stabilité et la sécurité du système. Cette fonctionnalité est UNIQUEMENT réservée aux diagnostics matériels effectués par le fabricant ou l\'opérateur."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"Activer ou désactiver des éléments de l\'application"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Permet à l\'application de monter et démonter des systèmes de fichiers pour des périphériques de stockage amovibles."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"Formatage du périphérique de stockage externe"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Permet à l\'application de formater le périphérique de stockage amovible."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"obtenir des informations sur le stockage sécurisé"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Permet à l\'application d\'obtenir des informations sur le stockage sécurisé."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"créer un stockage sécurisé"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Permet à l\'application de créer un stockage sécurisé."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"détruire le stockage sécurisé"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Permet à l\'application de détruire le stockage sécurisé."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"monter/démonter le stockage sécurisé"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Permet à l\'application de monter/démonter le stockage sécurisé."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"renommer le stockage sécurisé"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Permet à l\'application de renommer le stockage sécurisé."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"obtenir des informations sur la mémoire de stockage interne"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Permet à l\'application d\'obtenir des informations sur le stockage interne."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"créer un stockage interne"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Permet à l\'application de créer une mémoire de stockage interne."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"détruire la mémoire de stockage interne"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permet à l\'application de détruire le stockage interne."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"installer/désinstaller la mémoire de stockage interne"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Permet l\'installation ou la désinstallation de la mémoire de stockage interne par l\'application."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"renommer la mémoire de stockage interne"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permet à l\'application de renommer le stockage interne."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"Contrôle du vibreur"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permet à l\'application de contrôler le vibreur."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"Contrôle de la lampe de poche"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Permet à une application de configurer le téléphone Bluetooth local, d\'identifier des périphériques distants et de les associer au téléphone."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Création de connexions Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Permet à une application d\'obtenir la configuration du téléphone Bluetooth local et de créer et accepter des connexions à des appareils associés."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"contrôler la communication en champ proche"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Autorise une application à communiquer avec des tags, cartes et lecteurs prenant en charge la communication en champ proche (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"Désactivation du verrouillage des touches"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permet à une application de désactiver le verrouillage des touches et toute sécurité par mot de passe. Exemple : Votre téléphone désactive le verrouillage du clavier lorsque vous recevez un appel, puis le réactive lorsque vous raccrochez."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Lecture des paramètres de synchronisation"</string>
@@ -420,23 +423,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Permet à une application de lire tous les mots, noms et expressions que l\'utilisateur a pu enregistrer dans son dictionnaire personnel."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"Enregistrement dans le dictionnaire défini par l\'utilisateur"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permet à une application d\'enregistrer de nouveaux mots dans le dictionnaire personnel de l\'utilisateur."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"Modifier/supprimer le contenu de la carte SD"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Autorise une application à écrire sur la carte SD."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modifier/supprimer le contenu de la mémoire de stockage USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"Modifier/supprimer le contenu de la carte SD"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Autorise une application à écrire sur la mémoire USB."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Autorise une application à écrire sur la carte SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"accéder au système de fichiers en cache"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permet à une application de lire et d\'écrire dans le système de fichiers en cache."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Limiter le mot de passe"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Restreint les types de mots de passe que vous êtes autorisé à utiliser."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Surveiller les tentatives de connexion"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Surveille les échecs de connexion au périphérique pour effectuer une action."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Réinitialiser le mot de passe"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Force l\'utilisation d\'un nouveau mot de passe, qui doit vous être communiqué par l\'administrateur pour que vous puissiez vous connecter."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Forcer le verrouillage"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Contrôle le verrouillage du périphérique, avec obligation de saisir à nouveau le mot de passe."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"effectuer/recevoir des appels Internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Permet à une application d\'utiliser le service SIP pour effectuer/recevoir des appels Internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Gérer le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Gérer le nombre de mots de passe incorrects saisis lors du déverrouillage de l\'écran et verrouiller le téléphone ou effacer toutes ses données après un certain nombre de tentatives"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Modifier le mot de passe de déverrouillage de l\'écran"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Modifier le mot de passe de déverrouillage de l\'écran"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Verrouiller l\'écran"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Gérer le mode et les conditions de verrouillage de l\'écran"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Effacer toutes les données"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Rétablit les paramètres d\'usine, supprimant toutes vos données sans demande de confirmation."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Indiquez le proxy global à utiliser pour ce mobile lorsque les règles sont activées. Seul l\'administrateur principal du mobile peut définir le proxy global effectif."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Effacer les données du téléphone sans avertissement, en restaurant les valeurs d\'usine"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Définir le proxy global du mobile"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Indiquez le proxy global à utiliser pour ce mobile lorsque les règles sont activées. Seul l\'administrateur principal du mobile peut définir le proxy global utilisé."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domicile"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Bureau"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Autre"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Personnalisé"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personnalisée"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Accueil"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Professionnelle"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Autre"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Saisissez le code PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Saisissez le mot de passe pour procéder au déverrouillage."</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Saisissez le code PIN pour procéder au déverrouillage."</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Conseil : Appuyez deux fois pour effectuer un zoom avant ou arrière."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Permettre le remplissage automatique du formulaire"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Autorise une application à modifier l\'historique du navigateur ou les favoris enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonction pour effacer ou modifier les données de votre navigateur."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"régler le réveil"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permet à l\'application de définir une alarme dans un utilitaire faisant office de réveil. Certains réveils risquent ne pas prendre en charge cette fonctionnalité."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifier les autorisations de géolocalisation du navigateur"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permet à une application de modifier les autorisations de géolocalisation du navigateur. Les applications malveillantes peuvent se servir de cette fonctionnalité pour envoyer des informations de lieu à des sites Web arbitraires."</string>
     <string name="save_password_message" msgid="767344687139195790">"Voulez-vous que le navigateur se souvienne de ce mot de passe ?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Forcer la fermeture"</string>
     <string name="report" msgid="4060218260984795706">"Rapport"</string>
     <string name="wait" msgid="7147118217226317732">"Attendre"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Application redirigée"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> est maintenant lancée."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Application lancée initialement : <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="smv_application" msgid="295583804361236288">"L\'application <xliff:g id="APPLICATION">%1$s</xliff:g> (processus <xliff:g id="PROCESS">%2$s</xliff:g>) a enfreint ses propres règles du mode strict."</string>
     <string name="smv_process" msgid="5120397012047462446">"Le processus <xliff:g id="PROCESS">%1$s</xliff:g> a enfreint ses propres règles du mode strict."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Tout afficher"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Stockage de masse USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Connecté à l\'aide d\'un câble USB"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Vous avez connecté votre téléphone à votre ordinateur à l\'aide d\'un câble USB. Sélectionnez le bouton ci-dessous pour copier des fichiers de votre ordinateur vers la carte SD de votre Android, ou inversement."</string>
-    <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activer le périphérique de stockage USB"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Un problème est survenu lors de l\'utilisation de votre carte SD en tant que périphérique de stockage USB."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Vous avez connecté votre téléphone à votre ordinateur à l\'aide d\'un câble USB. Sélectionnez le bouton ci-dessous pour copier des fichiers de votre ordinateur vers la mémoire de stockage USB de votre Android, ou inversement."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Vous avez connecté votre téléphone à votre ordinateur à l\'aide d\'un câble USB. Sélectionnez le bouton ci-dessous pour copier des fichiers de votre ordinateur vers la carte SD de votre Android, ou inversement."</string>
+    <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activer la mémoire de stockage USB"</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Un problème est survenu lors de l\'utilisation de votre mémoire de stockage USB comme mémoire de stockage de masse."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Un problème est survenu lors de l\'utilisation de votre carte SD comme mémoire de stockage de masse USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Connecté avec un câble USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Activez pour copier des fichiers vers/de votre ordinateur."</string>
-    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Éteindre le périphérique de stockage USB"</string>
-    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Sélectionner pour éteindre le périphérique de stockage USB"</string>
-    <string name="usb_storage_stop_title" msgid="660129851708775853">"Stockage USB en cours d\'utilisation"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Avant de mettre hors tension le stockage USB, assurez-vous d\'avoir désactivé (\"éjecté\") la carte SD de votre téléphone Android à partir de votre ordinateur."</string>
-    <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Désactiver le périphérique de stockage USB"</string>
-    <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Un problème est survenu lors de la mise hors tension du périphérique de stockage USB. Assurez-vous que l\'hôte USB a bien été désactivé, puis essayez à nouveau."</string>
-    <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Activer le périphérique de stockage USB"</string>
-    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si vous activez le périphérique de stockage USB, certaines applications que vous utilisez se fermeront et risquent de n\'être de nouveau disponibles qu\'après la désactivation du périphérique."</string>
+    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Désactiver la mémoire de stockage USB"</string>
+    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Sélectionner pour désactiver la mémoire de stockage USB"</string>
+    <string name="usb_storage_stop_title" msgid="660129851708775853">"Mémoire de stockage USB en cours d\'utilisation"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Avant de désactiver la mémoire de stockage USB, assurez-vous d\'avoir désinstallé (\"éjecté\") de votre ordinateur la mémoire de stockage USB de votre Android."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Avant de désactiver la mémoire de stockage USB, assurez-vous d\'avoir désinstallé (\"éjecté\") de votre ordinateur la carte SD de votre Android."</string>
+    <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Désactiver la mémoire de stockage USB"</string>
+    <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Un problème est survenu lors de la désactivation de la mémoire de stockage USB. Assurez-vous que l\'hôte USB a bien été désinstallé, puis réessayez."</string>
+    <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Activer la mémoire de stockage USB"</string>
+    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si vous activez la mémoire de stockage USB, certaines applications en cours d\'utilisation seront fermées. Elles risquent de rester indisponibles jusqu\'à ce que la mémoire de stockage USB soit désactivée."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Échec du fonctionnement USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formater la carte SD"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Voulez-vous vraiment formater la carte SD ? Toutes les données de cette carte seront perdues."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formater la mémoire USB"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formater la carte SD"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formater la mémoire de stockage USB en effaçant tous les fichiers ? Cette action est irréversible."</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Voulez-vous vraiment formater la carte SD ? Toutes les données de cette carte seront perdues."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB connecté"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Sélectionnez cette option pour désactiver le débogage USB."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Préparation de la carte SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Préparation de la mémoire de stockage USB"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Préparation de la carte SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Recherche d\'erreurs"</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Carte SD vide"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"La carte SD est vide ou son système de fichiers n\'est pas pris en charge."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Carte SD endommagée"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"La carte SD est endommagée. Vous devrez peut-être la reformater."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"Carte SD retirée inopinément"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Désactiver la carte SD avant de la retirer pour éviter toute perte de données."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"La carte SD peut être retirée en toute sécurité"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Vous pouvez retirer la carte SD en toute sécurité."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Carte SD manquante"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"La carte SD a été retirée. Insérez-en une autre."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Mémoire de stockage USB vide"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Carte SD vide"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Le stockage USB est vide ou son système de fichiers n\'est pas pris en charge."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"La carte SD est vide ou son système de fichiers n\'est pas pris en charge."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Stockage USB endommagé"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Carte SD endommagée"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"La mémoire de stockage USB est endommagée. Un reformatage est peut-être nécessaire."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"La carte SD est endommagée. Vous devrez peut-être la reformater."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Mémoire USB retirée inopinément"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Carte SD retirée inopinément"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Désinstaller la mémoire de stockage USB avant de la retirer pour éviter toute perte de données."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Désactiver la carte SD avant de la retirer pour éviter toute perte de données."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Retirez la mémoire USB en toute sécurité."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"La carte SD peut être retirée en toute sécurité"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"La mémoire de stockage USB peut être retirée en toute sécurité."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Vous pouvez retirer la carte SD en toute sécurité."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Mémoire de stockage USB retirée"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Carte SD manquante"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Mémoire de stockage USB retirée. Insérez un nouveau support."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"La carte SD a été retirée. Insérez-en une autre."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Aucune activité correspondante trouvée"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"mettre à jour les données statistiques du composant"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Permet de modifier les données statistiques collectées du composant. Cette option n\'est pas utilisée par les applications standard."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 correspondance"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Désinstallation de la mémoire de stockage USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Désinstallation de la carte SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Effacement de la  mémoire de stockage USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Effacement de la carte SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Impossible d\'effacer la mémoire de stockage USB"</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Impossible d\'effacer la carte SD"</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"La carte SD a été retirée sans avoir été désinstallée."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Vérification de la mémoire de stockage USB en cours."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Vérification de la carte SD en cours."</string>
+    <string name="media_removed" msgid="7001526905057952097">"La carte SD a été retirée."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"La mémoire de stockage USB est en cours d\'utilisation par l\'ordinateur."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"La carte SD est en cours d\'utilisation par l\'ordinateur."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"État du support externe inconnu"</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index ab37893..b5f725d 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Spegni"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Spegnimento..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Il telefono verrà spento."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recenti"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Nessuna applicazione recente."</string>
     <string name="global_actions" msgid="2406416831541615258">"Opzioni telefono"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Strumenti di sviluppo"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funzionalità necessarie soltanto agli sviluppatori di applicazioni."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Archiviazione"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Accesso alla scheda SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accesso all\'archivio USB."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accesso alla scheda SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"disattivare o modificare la barra di stato"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"barra di stato"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Consente a un\'applicazione di liberare spazio sul telefono eliminando file nella directory della cache dell\'applicazione. L\'accesso è generalmente limitato a processi di sistema."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Spostare risorse dell\'applicazione"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Consente a un\'applicazione di spostare risorse applicative da supporti interni a esterni e viceversa."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"Lettura dati di registro sensibili"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Consente a un\'applicazione di leggere vari file di registro del sistema per trovare informazioni generali sulle operazioni effettuate con il telefono. Tali file potrebbero contenere informazioni personali o riservate."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lettura/scrittura risorse di proprietà di diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Consente a un\'applicazione di leggere le risorse del gruppo diag e scrivere a esse, per esempio i file in /dev. Questa capacità potrebbe influire sulla stabilità e sicurezza del sistema. Dovrebbe essere utilizzata SOLTANTO per diagnostiche specifiche dell\'hardware effettuate dal produttore o dall\'operatore."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"attivazione/disattivazione componenti applicazioni"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Consente montaggio e smontaggio da parte dell\'applicazione dei filesystem degli archivi rimovibili."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formattazione archivio esterno"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Consente all\'applicazione di formattare l\'archivio rimovibile."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"recupero di informazioni sull\'archiviazione protetta"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Consente all\'applicazione di ottenere informazioni sull\'archiviazione protetta."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"creazione archiviazione protetta"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Consente all\'applicazione di creare un\'archiviazione protetta."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"eliminazione archiviazione protetta"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Consente all\'applicazione di eliminare l\'archiviazione protetta."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"montaggio/smontaggio archiviazione protetta"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Consente all\'applicazione di montare/smontare l\'archiviazione protetta."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"rinominazione archiviazione protetta"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Consente all\'applicazione di rinominare l\'archiviazione protetta."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"recupero di informazioni sull\'archivio interno"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Consente all\'applicazione di ottenere informazioni sull\'archivio interno."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"creazione archivio interno"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Consente all\'applicazione di creare un archivio interno."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"eliminazione archivio interno"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Consente all\'applicazione di eliminare l\'archivio interno."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"montaggio/smontaggio archivio interno"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Consente all\'applicazione di montare/smontare l\'archivio interno."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"ridenominazione archivio interno"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Consente all\'applicazione di rinominare l\'archivio interno."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"controllo vibrazione"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Consente all\'applicazione di controllare la vibrazione."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controllo flash"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Consente a un\'applicazione di configurare il telefono Bluetooth locale e di rilevare e abbinare dispositivi remoti."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"creazione connessioni Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Consente a un\'applicazione di visualizzare la configurazione del telefono Bluetooth locale e di stabilire e accettare connessioni con dispositivi associati."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"controllo Near Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Consente a un\'applicazione di comunicare con tag, schede e lettori NFC (Near Field Communication)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"disattivazione blocco tastiera"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Consente la disattivazione da parte di un\'applicazione del blocco tastiera e di eventuali protezioni tramite password associate. Un valido esempio è la disattivazione da parte del telefono del blocco tastiera quando riceve una telefonata in entrata, e la successiva riattivazione del blocco al termine della chiamata."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lettura impostazioni di sincronizz."</string>
@@ -420,22 +423,25 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Consente a un\'applicazione di leggere parole, nomi e frasi private che l\'utente potrebbe aver memorizzato nel dizionario utente."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"scrittura nel dizionario definito dall\'utente"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Consente a un\'applicazione di scrivere nuove parole nel dizionario utente."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"modificare/eliminare i contenuti della scheda SD"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Consente a un\'applicazione di scrivere sulla scheda SD."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modifica/eliminaz. archivio USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificare/eliminare i contenuti della scheda SD"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Consente di scrivere nell\'archivio USB."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Consente a un\'applicazione di scrivere sulla scheda SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"accesso al filesystem nella cache"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Consente a un\'applicazione di leggere e scrivere il filesystem nella cache."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Limita password"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Limita i tipi di password che sei autorizzato a utilizzare."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Controlla i tentativi di accesso"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Monitora i tentativi non riusciti di accedere al dispositivo per eseguire un\'azione."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Reimposta password"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Forza un nuovo valore per la password, chiedendo all\'amministratore di concedertelo prima di poter eseguire l\'accesso."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Forza blocco"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Controlla quando il dispositivo si blocca, chiedendoti di reinserire la password."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"effettuazione/ricezione chiamate Internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Consente a un\'applicazione di utilizzare il servizio SIP per effettuare/ricevere chiamate Internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Imposta regole password"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Monitora tentativi di sblocco dello schermo"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitora il numero di password errate inserite durante lo sblocco dello schermo e blocca il telefono o cancella tutti i dati del telefono se vengono inserite troppe password errate"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Cambia la password di sblocco dello schermo"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Cambia la password di sblocco dello schermo"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Blocca lo schermo"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Controlla come e quando si blocca lo schermo"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Cancella tutti i dati"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Esegui un ripristino di fabbrica, eliminando tutti i tuoi dati senza conferma."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Cancella i dati del telefono senza preavviso eseguendo un ripristino dati di fabbrica"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Imposta il proxy globale del dispositivo"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Imposta il proxy globale del dispositivo in modo da utilizzarlo mentre la norma è attiva. Il proxy globale effettivo è impostabile solo dal primo amministratore del dispositivo."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Lavoro"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Altro"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Personalizzato"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalizzato"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Lavoro"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Altro"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Inserisci il PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Inserisci password per sbloccare"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Inserisci PIN per sbloccare"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Suggerimento. Tocca due volte per aumentare/ridurre lo zoom."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Compila automaticamente il modulo"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Consente a un\'applicazione di modificare la cronologia o i segnalibri del browser memorizzati sul telefono. Le applicazioni dannose possono sfruttare questa possibilità per cancellare o modificare i dati del browser."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"impostazione allarmi nella sveglia"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Consente all\'applicazione di impostare un allarme in un\'applicazione sveglia installata. Alcune applicazioni sveglia potrebbero non supportare questa funzione."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifica le autorizzazioni di localizzazione geografica del browser"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Consente a un\'applicazione di modificare le autorizzazioni di localizzazione geografica del browser. Le applicazioni dannose possono utilizzare questa autorizzazione per consentire l\'invio di informazioni sulla posizione a siti web arbitrari."</string>
     <string name="save_password_message" msgid="767344687139195790">"Memorizzare la password nel browser?"</string>
@@ -750,19 +753,16 @@
     <string name="force_close" msgid="3653416315450806396">"Termina"</string>
     <string name="report" msgid="4060218260984795706">"Segnala"</string>
     <string name="wait" msgid="7147118217226317732">"Attendi"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Applicazione reindirizzata"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> è ora in esecuzione."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> già avviata."</string>
     <string name="smv_application" msgid="295583804361236288">"L\'applicazione <xliff:g id="APPLICATION">%1$s</xliff:g> (processo <xliff:g id="PROCESS">%2$s</xliff:g>) ha violato la norma StrictMode autoimposta."</string>
     <string name="smv_process" msgid="5120397012047462446">"Il processo <xliff:g id="PROCESS">%1$s</xliff:g> ha violato la norma StrictMode autoimposta."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> in esecuzione"</string>
     <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Seleziona per passare all\'applicazione"</string>
     <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Scambiare le applicazioni?"</string>
     <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Un\'altra applicazione già in esecuzione deve essere chiusa prima di poterne avviare un\'altra."</string>
-    <string name="old_app_action" msgid="493129172238566282">"Torna a <xliff:g id="OLD_APP">%1$s</xliff:g> "</string>
+    <string name="old_app_action" msgid="493129172238566282">"Torna a <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
     <string name="old_app_description" msgid="942967900237208466">"Non avviare la nuova applicazione."</string>
     <string name="new_app_action" msgid="5472756926945440706">"Avvia <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
     <string name="new_app_description" msgid="6830398339826789493">"Interrompi la vecchia applicazione senza salvare."</string>
@@ -800,25 +800,30 @@
     <string name="no_permissions" msgid="7283357728219338112">"Nessuna autorizzazione richiesta"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"Nascondi"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostra tutto"</b></string>
-    <string name="usb_storage_activity_title" msgid="2399289999608900443">"Archiviazione di massa USB"</string>
+    <string name="usb_storage_activity_title" msgid="2399289999608900443">"Archivio di massa USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB collegata"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Il telefono è stato collegato al computer tramite USB. Seleziona il pulsante sottostante se desideri copiare file tra il computer e la scheda SD di Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Il telefono è stato collegato al computer tramite USB. Seleziona il pulsante sottostante se desideri copiare file tra il computer e l\'archivio USB di Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Il telefono è stato collegato al computer tramite USB. Seleziona il pulsante sottostante se desideri copiare file tra il computer e la scheda SD di Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Attiva archivio USB"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Problema di utilizzo della scheda SD per l\'archiviazione USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Problema di utilizzo dell\'archivio USB come archivio di massa USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Problema di utilizzo della scheda SD come archivio di massa USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB collegata"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Seleziona per copiare file sul/dal tuo computer."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Disattiva archivio USB"</string>
-    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Seleziona per disattivare archivio USB."</string>
-    <string name="usb_storage_stop_title" msgid="660129851708775853">"Archiviazione USB in uso"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Prima di disattivare l\'archiviazione USB, assicurati di avere smontato (\"espulso\") la scheda SD di Android dal computer."</string>
-    <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Disattiva archiviazione USB"</string>
-    <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Si è verificato un problema durante la disattivazione dell\'archiviazione USB. Verifica di avere smontato l\'host USB e riprova."</string>
+    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Seleziona per disattivare l\'archivio USB."</string>
+    <string name="usb_storage_stop_title" msgid="660129851708775853">"Archivio USB in uso"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Prima di disattivare l\'archivio USB, assicurati di avere smontato (\"espulso\") l\'archivio USB di Android dal computer."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Prima di disattivare l\'archivio USB, assicurati di avere smontato (\"espulso\") la scheda SD di Android dal computer."</string>
+    <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Disattiva archivio USB"</string>
+    <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Si è verificato un problema durante la disattivazione dell\'archivio USB. Assicurati di avere smontato l\'host USB e riprova."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Attiva archivio USB"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se attivi l\'archivio USB, alcune applicazioni in uso si bloccheranno e potrebbero risultare non disponibili finché non disattiverai l\'archivio USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operazione USB non riuscita"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formatta scheda SD"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Formattare la scheda SD? Tutti i dati sulla scheda verranno persi."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatta archivio USB"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatta scheda SD"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formattare l\'archivio USB cancellando tutti i file memorizzati al suo interno? Questa azione è irreversibile."</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Formattare la scheda SD? Tutti i dati sulla scheda verranno persi."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatta"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Debug USB collegato"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Seleziona per disattivare il debug USB."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidati"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Preparazione scheda SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Preparazione archivio USB"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Preparazione scheda SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Ricerca errori."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Scheda SD vuota"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"Scheda SD vuota o con filesystem non supportato."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Scheda SD danneggiata"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"Scheda SD danneggiata. Potrebbe essere necessario riformattarla."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"Rimozione imprevista della scheda SD"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Smonta scheda SD prima della rimozione per evitare la perdita di dati."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"È possibile rimuovere la scheda SD"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Puoi rimuovere la scheda SD in tutta sicurezza."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Scheda SD rimossa"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"Scheda SD rimossa. Inseriscine un\'altra."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Archivio USB vuoto"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Scheda SD vuota"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Archivio USB vuoto o con filesystem non supportato."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Scheda SD vuota o con filesystem non supportato."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Archivio USB danneggiato"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Scheda SD danneggiata"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Archivio USB danneggiato. Potrebbe essere necessario riformattarlo."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Scheda SD danneggiata. Potrebbe essere necessario riformattarla."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Rimozione imprevista archivio USB"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Rimozione imprevista della scheda SD"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Smonta l\'archivio USB prima della rimozione per evitare la perdita di dati."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Smonta scheda SD prima della rimozione per evitare la perdita di dati."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Puoi rimuovere l\'archivio USB"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"È possibile rimuovere la scheda SD"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Puoi rimuovere l\'archivio USB in tutta sicurezza."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puoi rimuovere la scheda SD in tutta sicurezza."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Archivio USB rimosso"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Scheda SD rimossa"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Archivio USB rimosso. Inserisci un nuovo supporto."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Scheda SD rimossa. Inseriscine un\'altra."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nessuna attività corrispondente trovata"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"aggiornare le statistiche di utilizzo dei componenti"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Consente la modifica delle statistiche di utilizzo dei componenti raccolte. Da non usare per normali applicazioni."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 corrispondenza"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> di <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Smontaggio dell\'archivio USB in corso..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Smontaggio scheda SD in corso..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Cancellazione dell\'archivio USB in corso..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Cancellazione scheda SD in corso..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Cancellazione dell\'archivio USB non riuscita."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Cancellazione della scheda SD non riuscita."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"La scheda SD è stata rimossa prima che fosse smontata."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Controllo dell\'archivio USB in corso."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Controllo della scheda SD in corso."</string>
+    <string name="media_removed" msgid="7001526905057952097">"La scheda SD è stata rimossa."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"L\'archivio USB è attualmente utilizzato da un computer."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"La scheda SD è attualmente utilizzata da un computer."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Stato dei supporti esterni sconosciuto."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 6ad7a750..ed0d357 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"電源を切る"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"シャットダウン中..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"携帯電話の電源を切ります。"</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"新着"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"最近使ったアプリケーションはありません。"</string>
     <string name="global_actions" msgid="2406416831541615258">"携帯電話オプション"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"開発ツール"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"アプリケーションのデベロッパーにのみ必要な機能です。"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"ストレージ"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"SDカードにアクセスします。"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"USBストレージへのアクセス"</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"SDカードにアクセスします。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ステータスバーの無効化や変更"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"ステータスバーの無効化やシステムアイコンの追加や削除をアプリケーションに許可します。"</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"ステータスバーへの表示"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"アプリケーションのキャッシュディレクトリからファイルを削除して携帯電話のメモリを解放することをアプリケーションに許可します。通常、アクセスはシステムプロセスのみに制限されます。"</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"アプリケーションリソースの移動"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"内部と外部のメディア間でのアプリケーションリソースの移動をアプリケーションに許可します。"</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"機密ログデータの読み取り"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"システムの各種ログファイルの読み取りをアプリケーションに許可します。許可すると端末の使用状況に関する全般的な情報が読み取られます。この情報には個人情報や機密情報が含まれる場合があります。"</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"diagが所有するリソースの読み書き"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"diagグループが所有するリソース(例:/dev内のファイル)への読み書きをアプリケーションに許可します。システムの安定性とセキュリティに影響する恐れがあります。メーカー/オペレーターによるハードウェア固有の診断以外には使用しないでください。"</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"アプリケーションのコンポーネントを有効/無効にする"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"リムーバブルメモリのファイルシステムのマウントとマウント解除をアプリケーションに許可します。"</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"外部ストレージのフォーマット"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"アプリケーションがリムーバブルストレージをフォーマットすることを許可します。"</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"セキュアストレージ上の情報の取得"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"セキュアストレージ上の情報の取得をアプリケーションに許可します。"</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"セキュアストレージの作成"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"セキュアストレージの作成をアプリケーションに許可します。"</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"セキュアストレージの破棄"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"セキュアストレージの破棄をアプリケーションに許可します。"</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"セキュアストレージのマウント/マウント解除"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"セキュアストレージのマウント/マウント解除をアプリケーションに許可します。"</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"セキュアストレージ名の変更"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"セキュアストレージ名の変更をアプリケーションに許可します。"</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"内部ストレージ上の情報の取得"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"内部ストレージ上の情報の取得をアプリケーションに許可します。"</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"内部ストレージの作成"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"内部ストレージの作成をアプリケーションに許可します。"</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"内部ストレージの破棄"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"内部ストレージの破棄をアプリケーションに許可します。"</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"内部ストレージのマウント/マウント解除"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"内部ストレージのマウント/マウント解除をアプリケーションに許可します。"</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"内部ストレージ名の変更"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"内部ストレージ名の変更をアプリケーションに許可します。"</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"バイブレーション制御"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"バイブレーションの制御をアプリケーションに許可します。"</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"ライトのコントロール"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"このBluetooth端末の設定、およびリモート端末を検出してペアに設定することをアプリケーションに許可します。"</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth接続の作成"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"このBluetooth端末の設定表示、および別の端末をペアとして設定し接続を承認することをアプリケーションに許可します。"</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"NFCの管理"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"NFCタグ、カード、リーダーとの通信をアプリケーションに許可します。"</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"キーロックを無効にする"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"キーロックや関連するパスワードセキュリティを無効にすることをアプリケーションに許可します。正当な利用の例では、かかってきた電話を受信する際にキーロックを無効にし、通話の終了時にキーロックを有効にし直します。"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"同期設定の読み取り"</string>
@@ -416,26 +419,29 @@
     <string name="permdesc_subscribedFeedsRead" msgid="3622200625634207660">"現在同期しているフィードの詳細の取得をアプリケーションに許可します。"</string>
     <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"登録したフィードの書き込み"</string>
     <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"現在同期しているフィードの変更をアプリケーションに許可します。悪意のあるアプリケーションが同期フィードを変更する恐れがあります。"</string>
-    <string name="permlab_readDictionary" msgid="432535716804748781">"ユーザー定義辞書の読み込み"</string>
-    <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="permdesc_sdcardWrite" msgid="6643963204976471878">"SDカードへの書き込みをアプリケーションに許可します。"</string>
+    <string name="permlab_readDictionary" msgid="432535716804748781">"単語リストの読み込み"</string>
+    <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" product="nosdcard" msgid="85430876310764752">"USBストレージのコンテンツの変更/削除"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"SDカードのコンテンツを修正/削除する"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"USBストレージへの書き込みをアプリケーションに許可します。"</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"SDカードへの書き込みをアプリケーションに許可します。"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"キャッシュファイルシステムにアクセス"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"キャッシュファイルシステムへの読み書きをアプリケーションに許可します。"</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"パスワードの制限"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"使用できるパスワードの種類を制限します。"</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"ログインの監視"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"携帯電話へのログインの失敗を監視し、何らかの処置をとります。"</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"パスワードのリセット"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"パスワードを強制的に新しい値に変更します。ログインするには管理者からその値を通知してもらう必要があります。"</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"強制ロック"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"携帯電話のロック時を管理します。パスワードの再入力が必要となります。"</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"インターネット通話の発着信"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"インターネット通話の発着信にSIPサービスを使用することをアプリケーションに許可します。"</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"画面ロック解除パスワードの長さと使用できる文字数を制御する"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"画面ロック解除試行の監視"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"画面ロック解除のために入力されたパスワードが間違っていた回数を監視し、回数が多すぎる場合は端末をロックするか、端末内のデータをすべて削除します。"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"画面ロック解除パスワードの変更"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"画面ロック解除パスワードの変更"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"画面のロック"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"画面をロックする方法とタイミングを制御する"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"すべてのデータを消去"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"出荷時設定にリセットします。確認なしでデータがすべて削除されます。"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"警告せずにデータの初期化を実行して端末内のデータを消去します。"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"端末のグローバルプロキシを設定"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"ポリシーが有効になっている場合は端末のグローバルプロキシが使用されるように設定します。有効なグローバルプロキシを設定できるのは最初のデバイス管理者だけです。"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"自宅"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"勤務先"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"その他"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"カスタム"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"カスタム"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"自宅"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"勤務先"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"その他"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PINコードを入力"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"ロックを解除するにはパスワードを入力"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"ロックを解除するにはPINを入力"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"ヒント: ダブルタップで拡大/縮小できます。"</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"このフォームを自動入力"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ブラウザの履歴とブックマークを読み取る"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"ブラウザでアクセスしたすべてのURLおよびブラウザのすべてのブックマークの読み取りをアプリケーションに許可します。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"ブラウザの履歴とブックマークを書き込む"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"携帯電話に保存されているブラウザの履歴やブックマークの修正をアプリケーショに許可します。これにより悪意のあるアプリケーションが、ブラウザのデータを消去または変更する恐れがあります。"</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"アラームの設定"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"インストール済みアラームアプリケーションのアラーム設定をアプリケーションに許可します。この機能が実装されていないアラームアプリケーションもあります。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"ブラウザの位置情報へのアクセス権を変更"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"ブラウザの位置情報に対するアクセス権の変更をアプリケーションに許可します。この設定では、悪意のあるアプリケーションが任意のウェブサイトに位置情報を送信する可能性があります。"</string>
     <string name="save_password_message" msgid="767344687139195790">"このパスワードをブラウザで保存しますか?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"強制終了"</string>
     <string name="report" msgid="4060218260984795706">"レポート"</string>
     <string name="wait" msgid="7147118217226317732">"待機"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"アプリのリダイレクト"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g>が実行中です。"</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g>が最初に起動していました。"</string>
     <string name="smv_application" msgid="295583804361236288">"アプリケーション<xliff:g id="APPLICATION">%1$s</xliff:g>(プロセス<xliff:g id="PROCESS">%2$s</xliff:g>)でStrictModeポリシー違反がありました。"</string>
     <string name="smv_process" msgid="5120397012047462446">"プロセス<xliff:g id="PROCESS">%1$s</xliff:g>でStrictModeポリシー違反がありました。"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g>を実行中"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"すべて表示"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USBマスストレージ"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB接続"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"携帯電話をUSBでパソコンに接続しています。パソコンとAndroidのSDカード間でファイルをコピーするには、下のボタンを選択します。"</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"携帯端末をUSBでパソコンに接続しています。パソコンとAndroidのUSBストレージの間でファイルをコピーするには、下のボタンを選択します。"</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"携帯電話をUSBでパソコンに接続しています。パソコンとAndroidのSDカード間でファイルをコピーするには、下のボタンを選択します。"</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USBストレージをONにする"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"USBメモリにSDカードを使用する際に問題が発生しました。"</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"USBストレージをUSBマスストレージとして使用する際に問題が発生しました。"</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"USBをUSBマスストレージとして使用する際に問題が発生しました。"</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB接続"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"パソコンとの間でファイルをコピーします。"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USBストレージをOFFにする"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"USBストレージをOFFにする場合に選択します。"</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USBストレージを使用中"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"USBストレージをOFFにする前に、パソコンで必ずAndroidのSDカードのマウントを解除して(カードを取り出して)ください。"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"USBストレージをOFFにする前に、パソコンで必ずAndroidのUSBストレージのマウントを解除して(ストレージを取り出して)ください。"</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"USBストレージをOFFにする前に、パソコンで必ずAndroidのSDカードのマウントを解除して(カードを取り出して)ください。"</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USBストレージをOFFにする"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"USBストレージをOFFにする際に問題が発生しました。USBホストのマウントが解除されていることを確認してからもう一度お試しください。"</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"USBストレージをONにする"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USBストレージをONにすると、使用中のアプリケーションの一部が停止し、USBストレージをOFFにするまで使用できなくなる場合があります。"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB操作に失敗しました"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"SDカードをフォーマット"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"SDカードをフォーマットしてもよろしいですか?カード内のすべてのデータが失われます。"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USBストレージのフォーマット"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SDカードをフォーマット"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USBストレージをフォーマットして、保存されているすべてのファイルを消去しますか?この操作は元に戻せません。"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"SDカードをフォーマットしてもよろしいですか?カード内のすべてのデータが失われます。"</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"フォーマット"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USBデバッグが接続されました"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"USBデバッグを無効にする場合に選択します。"</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"候補"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"SDカードの準備中"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"USBストレージの準備中"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SDカードの準備中"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"エラーを確認しています。"</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"空のSDカード"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"SDカードが空か、サポート対象外のファイルシステムを使用しています。"</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"破損したSDカード"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"SDカードが破損しています。カードのフォーマットが必要な可能性があります。"</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"SDカードが予期せず取り外されました"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"データの喪失を防ぐためSDカードを取り外す前にマウントを解除してください。"</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"SDカードを安全に取り外しました"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"SDカードは安全に取り外せます。"</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"SDカードが取り外されています"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"SDカードが取り外されました。新しいカードを挿入してください。"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"空のUSBストレージ"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"空のSDカード"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USBストレージが空であるか、サポートされていないファイルシステムを使用しています。"</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SDカードが空か、サポート対象外のファイルシステムを使用しています。"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"破損したUSBストレージ"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"破損したSDカード"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USBストレージが破損しています。ストレージの再フォーマットが必要な可能性があります。"</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SDカードが破損しています。カードのフォーマットが必要な可能性があります。"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USBストレージが不適切に取り外されました"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SDカードが予期せず取り外されました"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"データの喪失を防ぐためUSBストレージを取り外す前にマウントを解除してください。"</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"データの喪失を防ぐためSDカードを取り外す前にマウントを解除してください。"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USBストレージの安全な取り外し"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SDカードを安全に取り外しました"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"USBストレージを安全に取り外せます。"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"SDカードは安全に取り外せます。"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USBストレージ取り外し済み"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SDカードが取り外されています"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USBストレージが取り外されています。新しいメディアを挿入してください。"</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SDカードが取り外されました。新しいカードを挿入してください。"</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"一致するアクティビティが見つかりません"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"コンポーネント使用状況に関する統計情報の更新"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"収集されたコンポーネント使用状況に関する統計情報の変更を許可します。通常のアプリケーションでは使用しません。"</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1件一致"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g>件"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"USBストレージのマウント解除中..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"SDカードのマウント解除中..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"USBストレージ内のデータを消去中..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"SDカード内のデータを消去中..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"USBストレージ内のデータを消去できませんでした。"</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"SDカード内のデータを消去できませんでした。"</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SDカードがマウント解除される前に取り外されました。"</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USBストレージは現在確認中です。"</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SDカードは現在確認中です。"</string>
+    <string name="media_removed" msgid="7001526905057952097">"SDカードが取り外されました。"</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USBストレージは現在パソコンで使用中です。"</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SDカードは現在パソコンで使用中です。"</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"外部メディアの状態は不明です。"</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 3b9bd3f..ab593f9 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"종료"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"종료 중..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"휴대전화가 종료됩니다."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"최근 사용한 앱"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"최근에 사용한 앱이 없습니다."</string>
     <string name="global_actions" msgid="2406416831541615258">"휴대전화 옵션"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"개발 도구"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"애플리케이션 개발자에게만 필요한 기능입니다."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"저장"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"SD 카드에 액세스합니다."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"USB 저장소에 액세스합니다."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"SD 카드에 액세스합니다."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"상태 표시줄 사용 중지 또는 수정"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"애플리케이션이 상태 표시줄을 사용 중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 합니다."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"상태 표시줄"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"애플리케이션이 애플리케이션 캐시 디렉토리에 있는 파일을 삭제하여 휴대전화의 저장공간을 늘릴 수 있도록 합니다. 액세스는 일반적으로 시스템 프로세스로 제한됩니다."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"애플리케이션 리소스 이동"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"애플리케이션이 애플리케이션 리소스를 내부에서 외부 미디어로 또는 그 반대로 이동할 수 있도록 합니다."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"중요한 로그 데이터 읽기"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"애플리케이션이 시스템의 다양한 로그 파일을 읽을 수 있도록 합니다. 이렇게 되면 애플리케이션은 개인정보 또는 비공개 정보를 포함하여 휴대전화로 수행하는 작업에 대한 일반적인 정보를 검색할 수 있습니다."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"진단 그룹 소유의 리소스 읽기/쓰기"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"애플리케이션이 진단 그룹 소유의 리소스(예: /dev에 있는 파일)를 읽고 쓸 수 있도록 합니다. 이 기능은 시스템 안정성 및 보안에 영향을 미칠 수 있으므로 제조업체 또는 사업자가 하드웨어 관련 진단을 수행하는 경우에만 사용해야 합니다."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"애플리케이션 구성 요소 사용 또는 사용 안함"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"애플리케이션이 이동식 저장소의 파일 시스템을 마운트하고 마운트 해제할 수 있도록 합니다."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"외부 저장소 포맷"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"애플리케이션이 이동식 저장소를 포맷할 수 있도록 합니다."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"보안 저장소에 대한 정보 가져오기"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"애플리케이션이 보안 저장소의 정보를 가져올 수 있도록 합니다."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"보안 저장소 만들기"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"애플리케이션이 보안 저장소를 만들 수 있도록 합니다."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"보안 저장소 제거"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"애플리케이션이 보안 저장소를 제거할 수 있도록 합니다."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"보안 저장소 마운트/마운트 해제"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"애플리케이션이 보안 저장소를 마운트/마운트 해제할 수 있도록 합니다."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"보안 저장소 이름 바꾸기"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"애플리케이션이 보안 저장소의 이름을 바꿀 수 있도록 합니다."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"내부 저장소에 대한 정보 가져오기"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"애플리케이션에서 내부 저장소의 정보를 가져올 수 있습니다."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"내부 저장소 만들기"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"애플리케이션에서 내부 저장소를 만들 수 있습니다."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"내부 저장소 제거"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"애플리케이션에서 내부 저장소를 제거할 수 있습니다."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"내부 저장소 마운트/마운트 해제"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"애플리케이션에서 내부 저장소를 마운트/마운트 해제할 수 있습니다."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"내부 저장소 이름 바꾸기"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"애플리케이션에서 내부 저장소의 이름을 바꿀 수 있습니다."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"진동 제어"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"애플리케이션이 진동을 제어할 수 있도록 합니다."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"카메라 플래시 제어"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"애플리케이션이 로컬 Bluetooth 휴대전화를 구성한 다음 원격 장치를 검색하여 페어링할 수 있도록 합니다."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth 연결 만들기"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"애플리케이션이 로컬 Bluetooth 전화의 구성을 보고 페어링된 장치에 연결하며 연결을 수락할 수 있도록 합니다."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"NFC(Near Field Communication) 제어"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"애플리케이션에서 NFC(Near Field Communication) 태그, 카드 및 리더와 통신할 수 있습니다."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"키 잠금 사용 중지"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"애플리케이션이 키 잠금 및 관련 비밀번호 보안을 사용 중지할 수 있도록 합니다. 예를 들어, 휴대전화가 수신전화를 받을 때 키 잠금을 사용 중지했다가 통화가 끝나면 키 잠금을 다시 사용할 수 있습니다."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"동기화 설정 읽기"</string>
@@ -420,23 +423,26 @@
     <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="permdesc_sdcardWrite" msgid="6643963204976471878">"애플리케이션이 SD 카드에 쓸 수 있도록 합니다."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"USB 저장소 콘텐츠 수정/삭제"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"SD 카드 콘텐츠 수정/삭제"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"애플리케이션에서 USB 저장소의 정보를 변경할 수 있습니다."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"애플리케이션이 SD 카드에 쓸 수 있도록 합니다."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"캐시 파일시스템 액세스"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"애플리케이션이 캐시 파일시스템을 읽고 쓸 수 있도록 합니다."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"비밀번호 제한"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"사용할 수 있는 비밀번호 유형을 제한합니다."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"로그인 시도 보기"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"몇 가지 작업을 수행하기 위해 기기에 대해 실패한 로그인 시도를 모니터링합니다."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"비밀번호 재설정"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"비밀번호를 새 값으로 강제 설정합니다. 이를 수행하려면 로그인하기 전에 관리자에게 새로 지정할 비밀번호 값을 요청해야 합니다."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"강제 잠금"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"기기가 잠겨 있을 때 작동하려면 비밀번호를 다시 입력해야 합니다."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"인터넷 전화 걸기/받기"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"애플리케이션에서 SIP 서비스를 사용하여 인터넷 전화를 걸거나 받을 수 있습니다."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"화면 잠금해제 비밀번호에 허용되는 길이 및 문자 수를 제어합니다."</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"화면 잠금해제 시 비밀번호를 잘못 입력한 횟수를 모니터링하고, 잘못된 비밀번호 입력 횟수가 너무 많은 경우 휴대전화를 잠그거나 휴대전화에 있는 데이터를 모두 지웁니다."</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"화면 잠금해제 비밀번호를 변경합니다."</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"화면 잠금해제 비밀번호를 변경합니다."</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"화면 잠금"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"화면을 잠그는 방법과 시기를 제어합니다."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"모든 데이터 삭제"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"초기화를 수행하여 모든 데이터를 확인하지 않고 삭제합니다."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"정책이 사용 설정되어 있는 동안 사용될 기기 글로벌 프록시를 설정합니다. 첫 번째 기기 관리자가 설정한 글로벌 프록시만 유효합니다."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"초기화를 수행하여 경고 없이 휴대전화 데이터를 지웁니다."</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"기기 전체 프록시 설정"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"정책이 사용 설정되어 있는 동안 사용될 기기 전체 프록시를 설정합니다. 첫 번째 기기 관리자가 설정한 전체 프록시만 유효합니다."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"집"</item>
     <item msgid="869923650527136615">"모바일"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"직장"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"기타"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"맞춤설정"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"맞춤설정"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"홈"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"직장"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"기타"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN 코드 입력"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"잠금을 해제하려면 비밀번호 입력"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"잠금을 해제하려면 PIN 입력"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"도움말: 축소/확대하려면 두 번 누릅니다."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"양식 자동완성"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"브라우저의 기록 및 북마크 읽기"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"애플리케이션이 브라우저로 방문한 모든 URL과 브라우저의 모든 북마크를 읽도록 허용합니다."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"브라우저의 기록 및 북마크 쓰기"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"애플리케이션이 휴대전화에 저장된 브라우저 기록 또는 북마크를 수정할 수 있도록 허용합니다. 이 경우 악성 애플리케이션이 브라우저의 데이터를 지우거나 수정할 수 있습니다."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"알람 시계에 알람 설정"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"실치된 알람 시계 애플리케이션에 알람을 설정하도록 허용합니다. 일부 알람 시계 애플리케이션은 이 기능을 구현하지 않을 수 있습니다."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"브라우저 위치 정보 수정 권한"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"애플리케이션이 브라우저의 위치 정보 권한을 수정할 수 있도록 합니다. 악성 애플리케이션이 이를 사용하여 임의의 웹사이트에 위치 정보를 보낼 수도 있습니다."</string>
     <string name="save_password_message" msgid="767344687139195790">"브라우저에 이 비밀번호를 저장하시겠습니까?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"닫기"</string>
     <string name="report" msgid="4060218260984795706">"신고"</string>
     <string name="wait" msgid="7147118217226317732">"대기"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"애플리케이션 리디렉션됨"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g>이(가) 실행 중입니다."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"원래 <xliff:g id="APP_NAME">%1$s</xliff:g>을(를) 실행했습니다."</string>
     <string name="smv_application" msgid="295583804361236288">"애플리케이션 <xliff:g id="APPLICATION">%1$s</xliff:g>(프로세스 <xliff:g id="PROCESS">%2$s</xliff:g>)이(가) 자체 시행 StrictMode 정책을 위반했습니다."</string>
     <string name="smv_process" msgid="5120397012047462446">"프로세스(<xliff:g id="PROCESS">%1$s</xliff:g>)가 자체 시행 StrictMode 정책을 위반했습니다."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> 실행 중"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"모두 표시"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB 대용량 저장소"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB 연결됨"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"USB를 통해 휴대전화를 컴퓨터에 연결했습니다. 컴퓨터와 Android의 SD 카드 간에 파일을 복사하려면 아래의 버튼을 선택하세요."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"USB를 통해 휴대전화를 컴퓨터에 연결했습니다. 컴퓨터와 Android의 USB 저장소 간에 파일을 복사하려면 아래의 버튼을 선택하세요."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"USB를 통해 휴대전화를 컴퓨터에 연결했습니다. 컴퓨터와 Android의 SD 카드 간에 파일을 복사하려면 아래의 버튼을 선택하세요."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USB 저장소 사용"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"USB 저장소로 SD 카드를 사용하는 동안 문제가 발생했습니다."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"USB 대용량 저장소로 공유 저장용량을 사용하는 동안 문제가 발생했습니다."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"USB 대용량 저장소로 SD 카드를 사용하는 동안 문제가 발생했습니다."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 연결됨"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"컴퓨터에 파일을 복사하거나 컴퓨터의 파일을 복사하려면 선택합니다."</string>
-    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB 저장소 끄기"</string>
-    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"USB 저장소 끄기를 선택하세요."</string>
+    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB 저장소 사용 안함"</string>
+    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"\'USB 저장소 사용 중지\'를 선택하세요."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB 저장소 사용 중"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"USB 저장소를 사용하지 않도록 설정하기 전에 컴퓨터에서 Android의 SD 카드를 마운트 해제했는지(꺼냈는지) 확인하시기 바랍니다."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"USB 저장소를 사용하지 않도록 설정하기 전에 컴퓨터에서 Android의 USB 저장소를 마운트 해제했는지(꺼냈는지) 확인하시기 바랍니다."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"USB 저장소를 사용하지 않도록 설정하기 전에 컴퓨터에서 Android의 SD 카드를 마운트 해제했는지(꺼냈는지) 확인하시기 바랍니다."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB 저장소 사용 안함"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"USB 저장소를 사용하지 않도록 설정하는 동안 문제가 발생했습니다. USB 호스트와 연결을 해제했는지 확인한 다음 다시 시도하세요."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"USB 저장소 사용"</string>
-    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB 저장소를 사용 설정하면 사용 중인 일부 애플리케이션이 중지되고 USB 저장소를 사용 중지할 때까지 사용할 수 없게 됩니다."</string>
+    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB 저장소를 사용하면 사용 중인 일부 애플리케이션이 중지되어 USB 저장소를 사용 중지할 때까지 사용할 수 없게 됩니다."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB 작업 실패"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"확인"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"SD 카드 포맷"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"SD 카드를 포맷하시겠습니까? 포맷하면 카드의 모든 데이터를 잃게 됩니다."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB 저장소 포맷"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD 카드 포맷"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB 저장소를 포맷하여 저장된 파일을 모두 지우시겠습니까? 수행한 후에는 작업을 취소할 수 없습니다."</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"SD 카드를 포맷하시겠습니까? 포맷하면 카드의 모든 데이터를 잃게 됩니다."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"포맷"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB 디버깅 연결됨"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"USB 디버깅을 사용하지 않으려면 선택합니다."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"가능한 원인"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"SD 카드 준비 중"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"USB 저장소 준비 중"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD 카드 준비 중"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"오류 확인 중입니다."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"빈 SD 카드"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"SD 카드가 비어 있거나 지원되지 않는 파일 시스템을 사용합니다."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"손상된 SD 카드"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"SD 카드가 손상되었습니다. 카드를 다시 포맷해야 할 수 있습니다."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"SD 카드가 예상치 않게 제거되었습니다."</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"데이터 손실을 피하려면 SD 카드를 제거하기 전에 마운트 해제합니다."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"SD 카드 제거 가능"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"안전하게 SD 카드를 제거할 수 있습니다."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"SD 카드 없음"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"SD 카드가 없습니다.  SD 카드를 넣으세요."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"USB 저장소 비어 있음"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"빈 SD 카드"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB 저장소가 비어 있거나 지원되지 않는 파일 시스템을 사용합니다."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD 카드가 비어 있거나 지원되지 않는 파일 시스템을 사용합니다."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB 저장소 손상됨"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"손상된 SD 카드"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB 저장소가 손상되었습니다. 다시 포맷해야 합니다."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD 카드가 손상되었습니다. 카드를 다시 포맷해야 할 수 있습니다."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB 저장소가 예기치 않게 제거됨"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD 카드가 예상치 않게 제거되었습니다."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"데이터 손실을 피하려면 USB 저장소를 제거하기 전에 마운트 해제합니다."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"데이터 손실을 피하려면 SD 카드를 제거하기 전에 마운트 해제합니다."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB 저장소 안전하게 제거"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD 카드 제거 가능"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"USB 저장소를 안전하게 제거할 수 있습니다."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"안전하게 SD 카드를 제거할 수 있습니다."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB 저장소 제거됨"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD 카드 없음"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB 저장소를 제거했습니다. 새 미디어를 삽입하세요."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD 카드가 없습니다.  SD 카드를 넣으세요."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"일치하는 활동이 없습니다."</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"구성 요소 사용 통계 업데이트"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"수집된 구성요소 사용 통계를 수정할 수 있는 권한을 부여합니다. 일반 애플리케이션은 이 권한을 사용하지 않습니다."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"검색결과 1개"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"USB 저장소 마운트 해제 중..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"SD 카드 마운트 해제 중..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"USB 저장소 지우는 중..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"SD 카드 지우는 중..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"USB 저장소를 지우지 못했습니다."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"SD 카드를 지우지 못했습니다."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD 카드가 마운트 해제되기 전에 제거되었습니다."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"현재 USB 저장소를 확인하는 중입니다."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"현재 SD 카드를 확인하는 중입니다."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD 카드가 제거되었습니다."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"현재 USB 저장소를 컴퓨터에서 사용하고 있습니다."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"현재 SD 카드를 컴퓨터에서 사용하고 있습니다."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"외부 미디어가 알 수 없는 상태입니다."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 831e183..e2dd8a0 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Slå av"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Avslutter…"</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Telefonen vil bli slått av."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nylig"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Ingen nylig brukte applikasjoner."</string>
     <string name="global_actions" msgid="2406416831541615258">"Telefoninnstillinger"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Utviklingsverktøy"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funksjonalitet kun utviklere trenger."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Lagring"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Tilgang til minnekortet."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Tilgang til USB-lagring."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Tilgang til minnekortet."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"deaktivere eller endre statusfeltet"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Lar applikasjonen deaktivere statusfeltet, samt legge til og fjerne systemikoner."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"statusrad"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Lar applikasjonen frigjøre lagringsplass ved å slette filer i applikasjoners hurtigbufferkatalog. Tilgangen er vanligvis sterkt begrenset, til systemprosesser."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Flytter programressurser"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Gir et program tillatelse til å flytte programressurser fra interne til eksterne medier og omvendt."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"les sensitive loggdata"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Lar programmet lese fra diverse loggfiler på systemet. Disse inneholder generell informasjon om hva som gjøres med telefonen, og kan inneholde personlig eller privat informasjon."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lese/skrive ressurser eid av diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Lar applikasjonen lese og skrive enhver ressurs eid av gruppen diag; for eksempel, filer i /dev. Dette kan potensielt påvirke systemets sikkerhet og stabilitet. Dette bør KUN brukes for maskinvarespesifikke diagnoseverktøy laget av operatøren eller produsenten."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"aktivere eller deaktigere applikasjonskomponenter"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Lar applikasjonen montere og avmontere filsystemer for uttagbar lagring."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatere ekstern lagringsplass"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Lar applikasjonen formatere ekstern lagringsplass."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"få informasjon om sikker lagring"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Tillater programmet å innhente informasjon om sikker lagring."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"opprette sikker lagring"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Tillater programmet å opprette sikker lagring."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"stenge sikker lagring"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Tillater programmet å stenge sikker lagring."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"koble til eller fra sikker lagring"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Tillater programmet å koble sikker lagring til eller fra."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"gi nytt navn til sikker lagring"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Tillater programmet å gi nytt navn til sikker lagring."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"få informasjon om intern lagring"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Tillater programmet å innhente informasjon om intern lagring."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"opprett intern lagring"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Tillater programmet å opprette intern lagring."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"slett intern lagring"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Tillater programmet å stenge intern lagring."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"koble til eller fra intern lagring"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Tillater programmet å koble intern lagring til eller fra."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"gi nytt navn til intern lagring"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Tillater programmet å gi nytt navn til intern lagring."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"kontrollere vibratoren"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Lar applikasjonen kontrollere vibratoren."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kontrollere lommelykten"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Lar applikasjonen konfigurere den lokale Bluetooth-telefonen, og å oppdage og pare med andre enheter."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"opprette Bluetooth-tilkoblinger"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Lar applikasjonen se konfigurasjonen til den lokale Bluetooth-telefonen, og å opprette og godta tilkoblinger med parede enheter."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"kontroller overføring av data med NFC-teknologi"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Tillater programmet å kommunisere data via koder, kort og lesere for NFC-teknologi."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"slå av tastaturlås"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Lar applikasjonen slå av tastaturlåsen og enhver tilknyttet passordsikkerhet. Et legitimt eksempel på dette er at telefonen slår av tastaturlåsen når den mottar et innkommende anrop, og så slår den på igjen når samtalen er over."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lese synkroniseringsinnstillinger"</string>
@@ -420,22 +423,25 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Lar applikasjonen lese private ord, navn og uttrykk som brukeren har lagret i den brukerdefinerte ordlisten."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"skrive til brukerdefinert ordliste"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Lar applikasjonen skrive nye ord til den brukerdefinerte ordlisten."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"redigere/slette innhold på minnekort"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Lar applikasjonen skrive til minnekortet."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"endre/slette innh. i USB-lagr."</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"redigere/slette innhold på minnekort"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Prog. skriver til USB-lagr."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Lar applikasjonen skrive til minnekortet."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"tilgang til bufrede filer"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillater et program å lese og skrive til bufrede filer."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Begrens passord"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Begrense typene passord du kan bruke."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Overvåk påloggingsforsøk"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Overvåk mislykkede påloggingsforsøk eller forsøk på handlinger på enheten."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Tilbakestill passordet"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Fremtving tilbakestilling av passord, slik at administratoren må gi deg et nytt passord når du skal logge deg på."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Obligatorisk låsing"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Kontrollerer når enheten låses. Du må skrive inn passordet på nytt for å låse den opp."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"foreta/motta Internett-anrop"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Tillater et program å bruke SIP-tjenesten til å foreta og motta Internett-anrop."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontroller tillatt lengde og tegn i passord for opplåsing av skjerm"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Overvåk antall feil passordforsøk ved opplåsing av skjerm. Lås telefonen eller slett alle data ved for mange feil passordforsøk"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Endre passord for opplåsing av skjerm"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Endre passord for opplåsing av skjerm"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Lås skjermen"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontroller hvordan og når skjermen låses"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Slett alle data"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Utfører tilbakestilling til fabrikkstandard. Alle data slettes uten varsel."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Tilbakestill telefonens data uten advarsel ved å utføre tilbakestilling til fabrikkstandard"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Angi enhetens globale mellomtjener"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Angir den globale mellomtjeneren på enheten som skal brukes når regelen er aktivert. Kun den opprinnelige administratoren av enheten kan angi den globale mellomtjeneren."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjemmenummer"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Arbeid"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Annen"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Egendefinert"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Egendefinert"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Startside"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbeid"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Annen"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Skriv inn PIN-kode:"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Skriv inn passord for å låse opp"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Skriv inn personlig kode for å låse opp"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Dobbelttrykk for å zoome inn og ut."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Fyll ut dette skjemaet automatisk"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Lar applikasjonen endre nettleserens logg og bokmerker lagret på telefonen. Ondsinnede applikasjoner kan bruke dette til å fjerne eller redigere nettleserens data."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"angi alarm i alarmklokke"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Lar programmet angi en alarm i et installert alarmklokkeprogram. Det kan hende at enkelte alarmklokkeprogrammer ikke implementerer denne funksjonen."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Endre nettleserens tillatelser for geografisk posisjonering"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Tillater programmet å endre nettleserens tillatelser for geografisk posisjonering. Skadelige programmer kan bruke denne funksjonen til å sende posisjonsopplysninger til vilkårlige nettsteder."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ønsker du at nettleseren skal huske dette passordet?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Tving avslutning"</string>
     <string name="report" msgid="4060218260984795706">"Rapportér"</string>
     <string name="wait" msgid="7147118217226317732">"Vent"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Programmet er omdirigert"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> kjører nå."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ble opprinnelig startet."</string>
     <string name="smv_application" msgid="295583804361236288">"Programmet <xliff:g id="APPLICATION">%1$s</xliff:g> (prosessen <xliff:g id="PROCESS">%2$s</xliff:g>) har brutt de selvpålagte StrictMode-retningslinjene."</string>
     <string name="smv_process" msgid="5120397012047462446">"Prosessen<xliff:g id="PROCESS">%1$s</xliff:g> har brutt de selvpålagte StrictMode-retningslinjene."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> kjører"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Vis alle"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-masselagring"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB koblet til"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Du har koblet telefonen til datamaskinen via USB. Velg knappen nedenfor hvis du vil kopiere filer mellom datamaskinen og minnekortet i telefonen."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Du har koblet telefonen til datamaskinen via USB. Velg knappen nedenfor hvis du vil kopiere filer mellom datamaskinen og USB-lagring for Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Du har koblet telefonen til datamaskinen via USB. Velg knappen nedenfor hvis du vil kopiere filer mellom datamaskinen og minnekortet i telefonen."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Slå på USB-lagring"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Det oppsto et problem med å bruke minnekortet ditt for USB-lagring."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Det oppstod et problem under USB-lagring for USB-enheten."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Det oppstod et problem under SD-kortet for USB-enheten."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB tilkoblet"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Velg om du ønsker å kopiere filer til/fra en datamaskin."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Slå av USB-lagring"</string>
-    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Velg for å slå av USB-lagring."</string>
+    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Velg dette alternativet for å slå av USB-lagring."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-lagring er i bruk"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Før du slår av USB-lagring, sjekk at du har avmontert telefonen på datamaskinen."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Før du slår av USB-lagring, må du kontrollere at du har koblet fra USB-lagringsenheten for Android fra datamaskinen."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Før du slår av USB-lagring, sjekk at du har avmontert telefonen på datamaskinen."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Slå av USB-lagring"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Det oppstod et problem ved deaktivering av USB-lagring. Kontroller at du har demontert USB-verten, og prøv på nytt."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Slå på USB-lagring"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du aktiverer USB-lagring, virker ikke lenger enkelte av programmene du bruker, og de kan være utilgjengelige inntil du deaktiverer USB-lagringen."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-operasjonen mislyktes"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formatere minnekort"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Er du sikker på at du ønsker å formatere minnekortet? Alle data på kortet vil gå tapt."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formaterer USB-lagring"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatere minnekort"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vil du formatere USB-lagring og slette alle lagrede filer? Handlingen kan ikke angres!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Er du sikker på at du ønsker å formatere minnekortet? Alle data på kortet vil gå tapt."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatér"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-debugging tilkoblet"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Velg for å deaktivere USB-debugging."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
     <string name="candidates_style" msgid="4333913089637062257">"TAG_FONT"<u>"kandidater"</u>"CLOSE_FONT"</string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Forbereder minnekort"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Forbereder USB-lagring"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Forbereder minnekort"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Sjekker for feil."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Tomt minnekort"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"Minnekortet er tomt eller har et ikke-støttet filsystem."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Skadet minnekort"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"Minnekortet er skadet. Du må kanskje formatere det."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"Minnekortet ble tatt ut uventet"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Avmonter minnekortet før det tas ut, for å unngå datatap."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"Trygt å ta ut minnekort"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Det er trygt å ta ut minnekortet."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Minnekortet ble tatt ut"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"Minnekortet ble fjernet. Sett inn et nytt."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"USB-lagring er tom"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tomt minnekort"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB-lagring er tom eller har et filsystem som ikke håndteres."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Minnekortet er tomt eller har et ikke-støttet filsystem."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB-lagring skadet"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Skadet minnekort"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB-lagring er skadet. Det kan være nødvendig å formatere enheten på nytt."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Minnekortet er skadet. Du må kanskje formatere det."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-lagring fjernet uventet"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Minnekortet ble tatt ut uventet"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Koble fra USB-lagring før enheten tas ut av maskinen for å unngå tap av data."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Avmonter minnekortet før det tas ut, for å unngå datatap."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB-lagring kan trygt fjernes"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Trygt å ta ut minnekort"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Det er trygt å ta ut enheten for USB-lagring."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Det er trygt å ta ut minnekortet."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB-lagring fjernet"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Minnekortet ble tatt ut"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB-lagring fjernet. Sett inn et nytt medium."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Minnekortet ble fjernet. Sett inn et nytt."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Fant ingen tilsvarende aktiviteter"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"oppdater statistikk over komponentbruk"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Tillater endring av innsamlet data om bruk av komponenter. Ikke ment for vanlige applikasjoner."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 treff"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> av <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Kobler fra USB-lagring ..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Kobler fra SD-kort ..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Sletter USB-lagring ..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Sletter SD-kort ..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Kan ikke slette USB-lagring."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Kan ikke slette SD-kort."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD-kort ble ikke koblet fra før fjerning."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB-lagring kontrolleres."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SD-kortet kontrolleres."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD-kortet er fjernet."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB-lagring er for øyeblikket i bruk av en datamaskin."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SD-kortet er for øyeblikket i bruk av en datamaskin."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Eksternt medium har ukjent tilstand."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 28fdcc1..a040df5 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Uitschakelen"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Uitschakelen..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Uw telefoon wordt uitgeschakeld."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recent"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Geen recente toepassingen."</string>
     <string name="global_actions" msgid="2406416831541615258">"Telefoonopties"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Ontwikkelingshulpprogramma\'s"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Functies die alleen door toepassingsontwikkelaars worden gebruikt."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Opslagruimte"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Toegang tot de SD-kaart."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Toegang krijgen tot USB-opslag."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Toegang tot de SD-kaart."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"statusbalk uitschakelen of wijzigen"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Hiermee kan een toepassing de statusbalk uitschakelen of systeempictogrammen toevoegen en verwijderen."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"statusbalk"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Hiermee kan een toepassing opslagruimte op de telefoon vrij maken door bestanden te verwijderen uit de cachemap van de toepassing. De toegang is doorgaans beperkt tot het systeemproces."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Toepassingsbronnen verplaatsen"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Een toepassing toestaan toepassingsbronnen te verplaatsen van interne naar externe media en omgekeerd."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"gevoelige logbestandsgegevens lezen"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Hiermee kan een toepassing de verschillende logbestanden van het systeem lezen. De toepassing kan op deze manier algemene informatie achterhalen over uw telefoongebruik, mogelijk inclusief persoonlijke of privé-informatie."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lezen/schrijven naar bronnen van diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Hiermee kan een toepassing lezen en schrijven naar elke bron die hoort bij de diagnostische groep, zoals bestanden in /dev. Hierdoor kan de systeemstabiliteit en -veiligheid worden beïnvloed. Dit mag ALLEEN worden gebruikt voor hardwarespecifieke diagnostiek door de fabrikant of operator."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"toepassingscomponenten in- of uitschakelen"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Hiermee kan de toepassing bestandssystemen koppelen en ontkoppelen voor verwisselbare opslagruimte."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"externe opslag formatteren"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Hiermee kan de toepassing de externe opslag formatteren."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"informatie over de beveiligde opslag verkrijgen"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Staat de toepassing toe informatie over de beveiligde opslag te verkrijgen."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"beveiligde opslag maken"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Staat de toepassing toe beveiligde opslag te maken."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"beveiligde opslag vernietigen"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Staat de toepassing toe de beveiligde opslag te vernietigen."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"beveiligde opslag koppelen/ontkoppelen"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Staat de toepassing toe de beveiligde opslag te koppelen/ontkoppelen."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"naam van beveiligde opslag wijzigen"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Staat de toepassing toe de naam van de beveiligde opslag te wijzigen."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"informatie over de interne opslag verkrijgen"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Hiermee kan de toepassing informatie over de interne opslag verkrijgen."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"interne opslag maken"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Hiermee kan de toepassing interne opslag maken."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"interne opslag vernietigen"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Hiermee kan de toepassing de interne opslag vernietigen."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"interne opslag koppelen/ontkoppelen"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Hiermee kan de toepassing de interne opslag koppelen/ontkoppelen."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"naam van interne opslag wijzigen"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Hiermee kan de toepassing de naam van de interne opslag wijzigen."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"trilstand beheren"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Hiermee kan de toepassing de trilstand beheren."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"zaklamp bedienen"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Hiermee kan een toepassing de lokale Bluetooth-telefoon configureren en externe apparaten zoeken en aansluiten."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth-verbindingen maken"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Hiermee kan een toepassing de configuratie van een lokale Bluetooth-telefoon bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"Near Field Communication regelen"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Hiermee kan een toepassing communiceren met NFC-tags (Near Field Communication), kaarten en lezers."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"toetsvergrendeling uitschakelen"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Hiermee kan een toepassing de toetsvergrendeling en bijbehorende wachtwoordbeveiliging uitschakelen. Een voorbeeld: de telefoon schakelt de toetsvergrendeling uit als er een oproep binnenkomt en schakelt de toetsvergrendeling weer in als de oproep is beëindigd."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"synchronisatie-instellingen lezen"</string>
@@ -420,23 +423,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Hiermee kan een toepassing privéwoorden, namen en woordcombinaties lezen die de gebruiker heeft opgeslagen in het gebruikerswoordenboek."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"schrijven naar door gebruiker gedefinieerd woordenboek"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Hiermee kan een toepassing nieuwe woorden schrijven naar het gebruikerswoordenboek."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"inhoud op de SD-kaart aanpassen/verwijderen"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Hiermee kan een toepassing schrijven naar de SD-kaart."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"inhoud van USB-opslag aanpassen/verwijderen"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"inhoud op de SD-kaart aanpassen/verwijderen"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Hiermee kan een toepassing schrijven naar de USB-opslag."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Hiermee kan een toepassing schrijven naar de SD-kaart."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"het cachebestandssysteem openen"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Staat een toepassing toe het cachebestandssysteem te lezen en te schrijven."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Wachtwoord beperken"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"De typen wachtwoorden beperken die u mag gebruiken."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Aanmeldingspogingen controleren"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Mislukte pogingen controleren voor aanmelding bij het apparaat om een bepaalde actie uit te voeren."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Wachtwoord opnieuw instellen"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Uw wachtwoord gedwongen wijzigen in een nieuwe waarde, wat vereist dat de beheerder u het wachtwoord geeft voordat u zich kunt aanmelden."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Gedwongen vergrendelen"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Beheren wanneer het apparaat wordt vergrendeld, wat vereist dat u het wachtwoord opnieuw invoert."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"internetoproepen starten/ontvangen"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Hiermee kan een toepassing de SIP-service gebruiken om internetoproepen te starten/te ontvangen."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"De lengte en tekens beheren die zijn toegestaan in wachtwoorden voor schermontgrendeling"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de telefoon vergrendelen of alle gegevens op de telefoon wissen als er te veel onjuiste wachtwoorden worden ingevoerd"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Het wachtwoord voor schermontgrendeling wijzigen"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Het wachtwoord voor schermontgrendeling wijzigen"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Het scherm vergrendelen"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Beheren hoe en wanneer het scherm wordt vergrendeld"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Alle gegevens wissen"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"De fabrieksinstellingen herstellen, waarbij alle gegevens worden verwijderd zonder bevestiging."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Stel de algemene proxy voor het apparaat in die moet worden gebruikt terwijl het beleid is geactiveerd. Alleen de eerste apparaatbeheerder stelt de algemene proxy is."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"De gegevens van de telefoon zonder waarschuwing wissen door de fabrieksinstellingen te herstellen"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Algemene proxy voor het apparaat instellen"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Stel de algemene proxy voor het apparaat in die moet worden gebruikt terwijl het beleid is geactiveerd. Alleen de eerste apparaatbeheerder stelt de algemene proxy in."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Thuis"</item>
     <item msgid="869923650527136615">"Mobiel"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Werk"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Overig"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Aangepast"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Aangepast"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Startpagina"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Werk"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Overig"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN-code invoeren"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Voer het wachtwoord in om te ontgrendelen"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Voer de PIN-code in om te ontgrendelen"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Tip: tik tweemaal om in of uit te zoomen."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Dit formulier automatisch aanvullen"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Hiermee kan een toepassing de op uw telefoon opgeslagen browsergeschiedenis of bladwijzers wijzigen. Schadelijke toepassingen kunnen hiermee uw browsergegevens verwijderen of wijzigen."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"alarm instellen in wekker"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Hiermee kan de toepassing een alarm instellen in een geïnstalleerde wekkertoepassing. Deze functie wordt door sommige wekkertoepassingen niet geïmplementeerd."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Geolocatierechten voor browser aanpassen"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Staat een toepassing toe de geolocatierechten van de browser aan te passen. Schadelijke toepassingen kunnen dit gebruiken om locatiegegevens te verzenden naar willekeurige websites."</string>
     <string name="save_password_message" msgid="767344687139195790">"Wilt u dat de browser dit wachtwoord onthoudt?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Nu sluiten"</string>
     <string name="report" msgid="4060218260984795706">"Rapport"</string>
     <string name="wait" msgid="7147118217226317732">"Wachten"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Toepassing omgeleid"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> is nu actief."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> was het eerst gestart."</string>
     <string name="smv_application" msgid="295583804361236288">"De toepassing <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) heeft het zelf afgedwongen StrictMode-beleid geschonden."</string>
     <string name="smv_process" msgid="5120397012047462446">"Het proces <xliff:g id="PROCESS">%1$s</xliff:g> heeft het zelf afgedwongen StrictMode-beleid geschonden."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> wordt uitgevoerd"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Alles weergeven"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-massaopslag"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-verbinding"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"U heeft uw telefoon via USB op uw computer aangesloten. Selecteer de onderstaande knop als u bestanden tussen uw computer en de SD-kaart van uw Android wilt kopiëren."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"U heeft uw telefoon via USB op uw computer aangesloten. Selecteer de onderstaande knop als u bestanden tussen uw computer en de USB-opslag van uw Android wilt kopiëren."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"U heeft uw telefoon via USB op uw computer aangesloten. Selecteer de onderstaande knop als u bestanden tussen uw computer en de SD-kaart van uw Android wilt kopiëren."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USB-opslag inschakelen"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Er is een probleem bij het gebruik van uw SD-kaart voor USB-opslag."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Er is een probleem bij het gebruik van uw USB-opslag voor USB-massaopslag."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Er is een probleem bij het gebruik van uw SD-kaart voor USB-massaopslag."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB-verbinding"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Selecteer dit om bestanden naar/van uw computer te kopiëren."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB-opslag uitschakelen"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Selecteer dit om USB-opslag uit te schakelen."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-opslag in gebruik"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Voordat u USB-opslag uitschakelt, moet u de SD-kaart van uw Android hebben ontkoppeld (\'uitgeworpen\') van uw computer."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Voordat u USB-opslag uitschakelt, moet u de USB-opslag van uw Android hebben ontkoppeld (\'uitgeworpen\') van uw computer."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Voordat u USB-opslag uitschakelt, moet u de SD-kaart van uw Android hebben ontkoppeld (\'uitgeworpen\') van uw computer."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB-opslag uitschakelen"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Er is een probleem opgetreden tijdens het uitschakelen van de USB-opslag. Controleer of u de USB-host heeft losgekoppeld en probeer het opnieuw."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"USB-opslag inschakelen"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Als u USB-opslag inschakelt, worden bepaalde toepassingen die u gebruikt, gestopt en worden deze mogelijk pas weer beschikbaar wanneer u USB-opslag uitschakelt."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-bewerking mislukt"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"SD-kaart formatteren"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Weet u zeker dat u de SD-kaart wilt formatteren? Alle gegevens op uw kaart gaan dan verloren."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB-opslag formatt."</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-kaart formatteren"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB-opslag formatteren en alle opgeslagen bestanden wissen? Actie kan niet ongedaan worden gemaakt."</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Weet u zeker dat u de SD-kaart wilt formatteren? Alle gegevens op uw kaart gaan dan verloren."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatteren"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-foutopsporing verbonden"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Selecteer deze optie om USB-foutopsporing uit te schakelen."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaten"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"SD-kaart voorbereiden"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"USB-opslag voorbereiden"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD-kaart voorbereiden"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Controleren op fouten."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Lege SD-kaart"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"SD-kaart is leeg of heeft een niet-ondersteund bestandssysteem."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Beschadigde SD-kaart"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"SD-kaart beschadigd. U moet de kaart mogelijk opnieuw formatteren."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"SD-kaart onverwachts verwijderd"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Ontkoppel de SD-kaart voordat u deze verwijdert om gegevensverlies te voorkomen."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"De SD-kaart kan veilig worden verwijderd"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"U kunt de SD-kaart veilig verwijderen."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"SD-kaart is verwijderd"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"SD-kaart verwijderd. Plaats een nieuwe."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Lege USB-opslag"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Lege SD-kaart"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB-opslag leeg of heeft een niet-ondersteund bestandssysteem."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-kaart is leeg of heeft een niet-ondersteund bestandssysteem."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB-opslag beschadigd"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Beschadigde SD-kaart"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB-opslag beschadigd. U moet de opslag mogelijk opnieuw formatteren."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD-kaart beschadigd. U moet de kaart mogelijk opnieuw formatteren."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-opslag onverwachts verwijderd"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-kaart onverwachts verwijderd"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Ontkoppel de USB-opslag voordat u deze verwijdert om gegevensverlies te voorkomen."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Ontkoppel de SD-kaart voordat u deze verwijdert om gegevensverlies te voorkomen."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB-opslag veilig verwijderen"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"De SD-kaart kan veilig worden verwijderd"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"U kunt de USB-opslag veilig verwijderen."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"U kunt de SD-kaart veilig verwijderen."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB-opslag verwijderd"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD-kaart is verwijderd"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB-opslag verwijderd. Plaats nieuw medium."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-kaart verwijderd. Plaats een nieuwe."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Geen overeenkomende activiteiten gevonden"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"gebruiksstatistieken van component bijwerken"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Hiermee kunnen verzamelde gebruiksstatistieken van een component worden gewijzigd. Niet voor gebruik door normale toepassingen."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 overeenkomst"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> van <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"USB-opslag ontkoppelen..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"SD-kaart ontkoppelen..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"USB-opslag wissen..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"SD-kaart wissen..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Wissen van USB-opslag is mislukt."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Wissen van SD-kaart is mislukt."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD-kaart is verwijderd voordat deze is ontkoppeld."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB-opslag wordt momenteel gecontroleerd."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SD-kaart wordt momenteel gecontroleerd."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD-kaart is verwijderd."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB-opslag wordt momenteel gebruikt door een computer."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SD-kaart wordt momenteel gebruikt door een computer."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Extern medium heeft onbekende status."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 33b03ad..215a477 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Wyłącz"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Wyłączanie..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Telefon zostanie wyłączony"</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Najnowsze"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Brak ostatnio używanych aplikacji."</string>
     <string name="global_actions" msgid="2406416831541615258">"Opcje telefonu"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Narzędzia programistyczne"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funkcje potrzebne jedynie programistom"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Pamięć"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Dostęp do karty SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Dostęp do nośnika USB."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Dostęp do karty SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"wyłączanie lub zmienianie paska stanu"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Pozwala aplikacjom na wyłączenie paska stanu lub dodawanie i usuwanie ikon systemowych."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"pasek stanu"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Pozwala aplikacji na zwalnianie pamięci telefonu przez usuwanie plików z katalogu pamięci podręcznej aplikacji. Dostęp jest bardzo ograniczony, z reguły do procesów systemu."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Przenoszenie zasobów aplikacji"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Zezwala aplikacji na przeniesienie zasobów aplikacji z nośnika wewnętrznego na zewnętrzny i odwrotnie."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"odczyt wrażliwych danych dziennika"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Umożliwia aplikacjom odczyt z różnych plików dzienników systemowych. Pozwala to poznać ogólne informacje na temat korzystania z telefonu, co potencjalnie może obejmować również informacje prywatne lub osobiste."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"czytanie/zapisywanie w zasobach należących do diagnostyki"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Pozwala aplikacji na czytanie i zapisywanie we wszystkich zasobach posiadanych przez diagnozowaną grupę, jak na przykład pliki w katalogu /dev. Może to potencjalnie wpłynąć na stabilność i bezpieczeństwo systemu. Powinno być wykorzystywane TYLKO w celach diagnozowania sprzętu przez producenta lub operatora."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"włączanie lub wyłączanie składników aplikacji"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Pozwala aplikacjom na podłączanie i odłączanie systemów plików w pamięciach przenośnych."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatowanie pamięci zewnętrznej"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Zezwala aplikacji na formatowanie wymiennych nośników."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"uzyskiwanie informacji o bezpiecznym magazynie"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Zezwala aplikacji na uzyskiwanie informacji o bezpiecznym magazynie."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"tworzenie bezpiecznego magazynu"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Zezwala aplikacji na tworzenie bezpiecznego magazynu."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"usuwanie bezpiecznego magazynu"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Zezwala aplikacji na usuwanie bezpiecznego magazynu."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"podłączanie/odłączanie bezpiecznego magazynu"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Zezwala aplikacji na podłączanie/odłączanie bezpiecznego magazynu."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"zmiana nazwy bezpiecznego magazynu"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Zezwala aplikacji na zmianę nazwy bezpiecznego magazynu."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"uzyskiwanie informacji o pamięci wewnętrznej"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Zezwala aplikacji na uzyskiwanie informacji o pamięci wewnętrznej."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"tworzenie pamięci wewnętrznej"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Zezwala aplikacji na tworzenie pamięci wewnętrznej."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"likwidacja pamięci wewnętrznej"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Zezwala aplikacji na likwidowanie pamięci wewnętrznej."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"podłączanie/odłączanie pamięci wewnętrznej"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Zezwala aplikacji na podłączanie/odłączanie pamięci wewnętrznej."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"zmiana nazwy pamięci wewnętrznej"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Zezwala aplikacji na zmianę nazwy pamięci wewnętrznej."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"kontrolowanie wibracji"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Pozwala aplikacjom na kontrolowanie wibracji."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kontrolowanie latarki"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Pozwala aplikacji na konfigurowanie lokalnego telefonu Bluetooth, wyszukiwanie urządzeń zdalnych i łączenie się z nimi."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"tworzenie połączeń Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Pozwala aplikacji na wyświetlanie konfiguracji lokalnego telefonu Bluetooth oraz na tworzenie i akceptowanie połączeń ze sparowanymi urządzeniami."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"kontrolowanie łączności Near Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Zezwala aplikacji na komunikowanie się z użyciem tagów, kart i czytników Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"wyłączanie blokady klawiatury"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Pozwala aplikacji na wyłączenie blokady klawiatury i wszystkich związanych z tym haseł zabezpieczających. Typowym przykładem takiego działania jest wyłączanie blokady klawiatury, gdy pojawia się połączenie przychodzące, a następnie ponowne jej włączanie po zakończeniu połączenia."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"czytanie ustawień synchronizowania"</string>
@@ -420,23 +423,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Zezwala aplikacji na odczytywanie wszelkich prywatnych słów, nazw i wyrażeń zapisanych przez użytkownika w swoim słowniku."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"zapisywanie w słowniku zdefiniowanym przez użytkownika"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Zezwala aplikacjom na zapisywanie nowych słów w słowniku użytkownika."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"modyfikowanie/usuwanie zawartości karty SD"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Umożliwia aplikacji zapis na karcie SD."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modyfik./usuwan. z nośnika USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modyfikowanie/usuwanie zawartości karty SD"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Umożliwia zapis na nośnik USB."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Umożliwia aplikacji zapis na karcie SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"dostęp do systemu plików pamięci podręcznej"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Zezwala aplikacji na odczyt i zapis w systemie plików pamięci podręcznej."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Ogranicz liczbę prób wprowadzenia hasła"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Ogranicza dozwolone typy haseł użytkownika."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Monitoruj próby logowania"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Monitoruje nieudane próby zalogowania do urządzenia w celu wykonania określonego działania."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Resetuj hasło"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Wymusza podanie nowej wartości hasła, wymagając przekazania go użytkownikowi przez administratora przed zalogowaniem."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Wymuś zablokowanie"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Kontroluje, kiedy urządzenie jest blokowane, wymagając ponownego wprowadzenia hasła."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"nawiązywanie/odbieranie połączeń przez internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Umożliwia aplikacji korzystanie z usługi SIP do nawiązywania/odbierania połączeń przez internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitorowanie liczby przypadków wprowadzenia nieprawidłowego hasła podczas odblokowywania ekranu oraz blokowanie telefonu lub wymazywanie z niego wszystkich danych po wprowadzeniu zbyt wielu nieprawidłowych haseł"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Zmień hasło odblokowania ekranu"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Zmień hasło odblokowania ekranu"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Zablokuj ekran"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrolowanie sposobu i warunków blokowania ekranu"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Usuń wszystkie dane"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Wykonuje reset fabryczny, usuwając wszystkie dane użytkownika bez żadnego potwierdzenia."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Ustaw globalny serwer proxy urządzenia do używania przy włączonych zasadach. Tylko pierwszy administrator urządzenia ustawia obowiązujący globalny serwer proxy."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Wymazywanie danych z telefonu bez ostrzeżenia, przez przywrócenie danych fabrycznych"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Ustaw globalny serwer proxy urządzenia"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Ustaw globalny serwer proxy urządzenia do wykorzystywania przy włączonych zasadach. Tylko pierwszy administrator urządzenia ustawia obowiązujący globalny serwer proxy."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Dom"</item>
     <item msgid="869923650527136615">"Komórka"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Służbowy"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Inny"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Niestandardowy"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Niestandardowy"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Domowy"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Służbowy"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Inny"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Wprowadź kod PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Wprowadź hasło, aby odblokować"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Wprowadź kod PIN, aby odblokować"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Wskazówka: dotknij dwukrotnie, aby powiększyć lub pomniejszyć."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Wypełnij ten formularz automatycznie"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Umożliwia aplikacji modyfikowanie historii lub zakładek przeglądarki zapisanych w telefonie. Złośliwe aplikacje mogą używać tej opcji do usuwania lub modyfikowania danych przeglądarki."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"ustaw alarm w budziku"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Umożliwia aplikacji ustawienie alarmu w zainstalowanej aplikacji budzika. W niektórych aplikacjach budzika funkcja ta może nie być zaimplementowana."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modyfikowanie uprawnień przeglądarki dotyczących lokalizacji geograficznej"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Zezwala aplikacji na modyfikowanie uprawnień przeglądarki dotyczących lokalizacji geograficznej. Złośliwe aplikacje mogą używać tej opcji do wysyłania informacji o lokalizacji do dowolnych witryn internetowych."</string>
     <string name="save_password_message" msgid="767344687139195790">"Czy chcesz, aby zapamiętać to hasło w przeglądarce?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Wymuś zamknięcie"</string>
     <string name="report" msgid="4060218260984795706">"Zgłoś"</string>
     <string name="wait" msgid="7147118217226317732">"Czekaj"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Aplikacja przekierowana"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest uruchomiona."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> została pierwotnie uruchomiona."</string>
     <string name="smv_application" msgid="295583804361236288">"Aplikacja <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) naruszyła wymuszone przez siebie zasady StrictMode."</string>
     <string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> naruszył wymuszone przez siebie zasady StrictMode."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Działa <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Pokaż wszystko"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Pamięć masowa USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Połączenie przez USB"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Telefon został połączony z komputerem za pośrednictwem USB. Wybierz poniższy przycisk, aby skopiować pliki między komputerem a kartą SD systemu Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Telefon został połączony z komputerem za pośrednictwem USB. Wybierz poniższy przycisk, aby skopiować pliki między komputerem a nośnikiem USB systemu Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Telefon został połączony z komputerem za pośrednictwem USB. Wybierz poniższy przycisk, aby skopiować pliki między komputerem a kartą SD systemu Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Włącz nośnik USB"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Wystąpił problem z wykorzystaniem karty SD dla pamięci USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Wystąpił problem z użyciem nośnika USB jako pamięci masowej USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Wystąpił problem z użyciem karty SD jako nośnika pamięci masowej USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Połączenie przez USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Wybierz, aby skopiować pliki do/z komputera"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Wyłącz nośnik USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Wybierz, aby wyłączyć nośnik USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Nośnik USB w użyciu"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Przed wyłączeniem nośnika USB upewnij się, że karta SD systemu Android została odłączona („wyjęta”) od komputera."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Przed wyłączeniem nośnika USB upewnij się, że nośnik USB systemu Android został odłączony od komputera („wyjęty”)."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Przed wyłączeniem nośnika USB upewnij się, że karta SD systemu Android została odłączona („wyjęta”) od komputera."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Wyłącz nośnik USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Wystąpił problem podczas wyłączania nośnika USB. Upewnij się, że host USB został odłączony, a następnie spróbuj ponownie."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Włącz nośnik USB"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Po włączeniu nośnika USB niektóre używane aplikacje zostaną zatrzymane i mogą być niedostępne do chwili wyłączenia nośnika USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operacja USB nie powiodła się"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formatuj kartę SD"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Czy na pewno sformatować kartę SD? Wszystkie dane na karcie zostaną utracone."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatuj nośnik USB"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatuj kartę SD"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Czy sformatować nośnik USB i wymazać wszystkie zapisane na nim pliki? Tej czynności nie można cofnąć."</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Czy na pewno sformatować kartę SD? Wszystkie dane na karcie zostaną utracone."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatuj"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Podłączono moduł debugowania USB"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Wybierz, aby wyłączyć debugowanie USB."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandydaci"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Przygotowywanie karty SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Przygotowywanie nośnika USB"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Przygotowywanie karty SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Sprawdzanie w poszukiwaniu błędów."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Pusta karta SD"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"Karta SD jest pusta lub zawiera nieobsługiwany system plików."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Uszkodzona karta SD"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"Karta SD jest uszkodzona. Konieczne może być ponowne sformatowanie."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"Karta SD została nieoczekiwanie wyjęta"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Odłącz kartę SD przed jej wyjęciem, aby uniknąć utraty danych."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"Można bezpiecznie usunąć kartę SD"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Możesz bezpiecznie wyjąć kartę SD."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Usunięta karta SD"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"Karta SD została wyjęta. Włóż nową kartę."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Pusty nośnik USB"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Pusta karta SD"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Nośnik USB jest pusty lub zawiera nieobsługiwany system plików."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Karta SD jest pusta lub zawiera nieobsługiwany system plików."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Uszkodzony nośnik USB"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Uszkodzona karta SD"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Nośnik USB jest uszkodzony. Konieczne może być ponowne sformatowanie."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Karta SD jest uszkodzona. Konieczne może być ponowne sformatowanie."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Nośnik USB został nagle wyjęty"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Karta SD została nieoczekiwanie wyjęta"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Odłącz nośnik USB przed jego wyjęciem, aby uniknąć utraty danych."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Odłącz kartę SD przed jej wyjęciem, aby uniknąć utraty danych."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Można wyjąć nośnik USB"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Można bezpiecznie usunąć kartę SD"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Możesz bezpiecznie wyjąć nośnik USB."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Możesz bezpiecznie wyjąć kartę SD."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Wyjęto nośnik USB"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Usunięta karta SD"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Nośnik USB został wyjęty. Włóż nowy nośnik."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Karta SD została wyjęta. Włóż nową kartę."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nie znaleziono pasujących działań"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"aktualizowanie statystyk użycia komponentu"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Zezwala na modyfikacje zebranych statystyk użycia komponentu. Nieprzeznaczone dla zwykłych aplikacji."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 wynik"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Odłączanie nośnika USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Odłączanie karty SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Czyszczenie nośnika USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Czyszczenie karty SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Nie można wyczyścić nośnika USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Nie można wyczyścić karty SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Karta SD została wyjęta przed jej odłączeniem."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Nośnik USB jest obecnie sprawdzany."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Karta SD jest obecnie sprawdzana."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Karta SD została wyjęta."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Nośnik USB jest obecnie używany przez komputer."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Karta SD jest obecnie używana przez komputer."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Nośnik zewnętrzny jest w nieznanym stanie."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index dc762d1..4bb4ddf 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Desligar"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"A encerrar..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"O seu telefone irá encerrar."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Nenhuma aplicação recente."</string>
     <string name="global_actions" msgid="2406416831541615258">"Opções do telefone"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Ferramentas de desenvolvimento"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funcionalidades apenas necessárias para programadores de aplicações."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Armazenamento"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Aceder ao cartão SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Aceder ao armazenamento USB."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Aceder ao cartão SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desactivar ou modificar barra de estado"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permite à aplicação desactivar a barra de estado ou adicionar e remover ícones do sistema."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"barra de estado"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Permite a uma aplicação libertar espaço de armazenamento no telefone eliminando ficheiros no directório da cache da aplicação. Geralmente, o acesso é muito limitado para processamento do sistema."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Mover recursos de aplicações"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Permite que uma aplicação mova recursos de aplicações de meios internos para meios externos e vice-versa."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"ler dados sensíveis de registo"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Permite a uma aplicação ler a partir dos diversos ficheiros de registo do sistema. Isto permite descobrir informações gerais sobre a forma como o utilizador usa o telefone, podendo, inclusive, incluir dados pessoais ou privados."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"ler/escrever em recursos propriedade de diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Permite a uma aplicação ler e escrever em qualquer recurso que seja propriedade do grupo diag. Por exemplo, ficheiros em /dev. Isto pode afectar potencialmente a estabilidade e a segurança do sistema e deve ser utilizado APENAS para diagnósticos específicos do hardware pelo fabricante ou pelo operador."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"activar ou desactivar componentes da aplicação"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Permite à aplicação montar e desmontar sistemas de ficheiros para armazenamento removível."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatar armazenamento externo"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Permite a uma aplicação formatar o armazenamento removível."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"obter informações sobre o armazenamento seguro"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Permite à aplicação obter informações sobre o armazenamento seguro."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"criar armazenamento seguro"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Permite à aplicação criar armazenamento seguro."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"destruir armazenamento seguro"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Permite à aplicação destruir o armazenamento seguro."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"instalar/desinstalar armazenamento seguro"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Permite à aplicação instalar/desinstalar o armazenamento seguro."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"mudar o nome do armazenamento seguro"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Permite à aplicação mudar o nome do armazenamento seguro."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"obter informações sobre o armazenamento interno"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Permite à aplicação obter informações sobre o armazenamento interno."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"criar armazenamento interno"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Permite à aplicação criar armazenamento interno."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"destruir armazenamento interno"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permite à aplicação destruir o armazenamento interno."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"montar/desmontar armazenamento interno"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Permite à aplicação montar/desmontar o armazenamento interno."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"mudar o nome do armazenamento interno"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permite à aplicação mudar o nome do armazenamento interno."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"controlar vibrador"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permite à aplicação controlar o vibrador."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controlar lanterna"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Permite a uma aplicação configurar o telefone Bluetooth local, bem como descobrir e emparelhar com dispositivos remotos."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"criar ligações Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Permite a uma aplicação ver a configuração do telefone Bluetooth local, bem como efectuar e aceitar ligações com dispositivos emparelhados."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"controlo Near Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Permite que uma aplicação comunique com etiquetas, cartões e leitores Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"desactivar bloqueio de teclas"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite a uma aplicação desactivar o bloqueio de teclas e qualquer segurança por palavra-passe associada. Um exemplo legítimo é a desactivação do bloqueio de teclas pelo telefone ao receber uma chamada, reactivando, em seguida, o bloqueio de teclas ao terminar a chamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler definições de sincronização"</string>
@@ -420,23 +423,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Permite a uma aplicação ler quaisquer palavras, nomes e expressões privadas que o utilizador possa ter armazenado no dicionário do utilizador."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"escrever no dicionário definido pelo utilizador"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permite a uma aplicação escrever novas palavras no dicionário do utilizador."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"modificar/eliminar conteúdo do cartão SD"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Permite que uma aplicação escreva no cartão SD."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"mod./elim. conteúdo do armaz. USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/eliminar conteúdo do cartão SD"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Permite que uma aplicação escreva no armaz. USB."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Permite que uma aplicação escreva no cartão SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"aceder ao sistema de ficheiros da cache"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite a uma aplicação ler e escrever no sistema de ficheiros da cache."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Limitar palavra-passe"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Restrinja os tipos de palavras-passe que está autorizado a utilizar."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Ver tentativas de início de sessão"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"O monitor falhou as tentativas de iniciar sessão no dispositivo para efectuar algumas acções."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Repor palavra-passe"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Force a palavra-passe para um novo valor, sendo necessário que o administrador lho forneça antes de poder iniciar sessão."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Forçar bloqueio"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Controle quando o dispositivo é bloqueado, sendo necessário reintroduzir a respectiva palavra-passe."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"fazer/receber chamadas pela internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Autoriza uma aplicação a utilizar o serviço SIP para fazer/receber chamadas pela internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlar o comprimento e os caracteres permitidos nas palavras-passe de desbloqueio do ecrã"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitorize o número de palavras-passe incorrectas introduzidas ao desbloquear o ecrã e bloqueie o telefone ou apague todos os dados do telefone se forem introduzidas demasiadas palavras-passe incorrectas"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Alterar a palavra-passe de desbloqueio do ecrã"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Alterar a palavra-passe de desbloqueio do ecrã"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloquear o ecrã"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Controlar como e quando ocorre o bloqueio do ecrã"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Apagar todos os dados"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Efectue uma reposição de fábrica, eliminando todos os dados sem qualquer confirmação."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Definir o proxy global do dispositivo a ser utilizado quando a política estiver activada. Só o primeiro administrador do dispositivo define o proxy global efectivo."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Apagar os dados do telefone sem avisar, ao efectuar uma reposição de dados de fábrica"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir o proxy global do aparelho"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Definir o proxy global do aparelho a ser utilizado quando a política estiver activada. Só o primeiro administrador do aparelho define o proxy global efectivo."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Residência"</item>
     <item msgid="869923650527136615">"Móvel"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Emprego"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Outro"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Personalizado"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalizado"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Página inicial"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Emprego"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Outro"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduzir código PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Introduza a palavra-passe para desbloquear"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Introduza o PIN para desbloquear"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Sugestão: toque duas vezes para aumentar ou diminuir o zoom."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Preenchimento automático deste formulário"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Permite que uma aplicação modifique o histórico e os marcadores do browser armazenados no telefone. As aplicações maliciosas podem utilizar esta permissão para apagar ou modificar os dados do browser."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"definir alarme no despertador"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que a aplicação defina um alarme numa aplicação de despertador instalada. Algumas aplicações de despertador podem não integrar esta funcionalidade."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar permissões de localização geográfica do Navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite a uma aplicação modificar as permissões de localização geográfica do Navegador. As aplicações mal intencionadas podem utilizar isto para enviar informações de localização para Web sites arbitrários."</string>
     <string name="save_password_message" msgid="767344687139195790">"Quer que o browser memorize esta palavra-passe?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Forçar fecho"</string>
     <string name="report" msgid="4060218260984795706">"Relatório"</string>
     <string name="wait" msgid="7147118217226317732">"Esperar"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Aplicação redireccionada"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> está agora a ser executado."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> foi originalmente iniciado."</string>
     <string name="smv_application" msgid="295583804361236288">"A aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> (processo <xliff:g id="PROCESS">%2$s</xliff:g>) violou a política StrictMode auto-imposta."</string>
     <string name="smv_process" msgid="5120397012047462446">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> violou a política StrictMode auto-imposta."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
@@ -800,25 +800,30 @@
     <string name="no_permissions" msgid="7283357728219338112">"Não são necessárias permissões"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"Ocultar"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar tudo"</b></string>
-    <string name="usb_storage_activity_title" msgid="2399289999608900443">"Armazenamento em massa USB "</string>
+    <string name="usb_storage_activity_title" msgid="2399289999608900443">"Armazenamento em massa USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Ligado através de USB"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Ligou o telefone ao computador através de USB. Seleccione o botão abaixo se pretender copiar ficheiros entre o computador e o cartão SD do Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Ligou o telemóvel ao computador através de USB. Seleccione o botão abaixo se pretender copiar ficheiros entre o computador e o armazenamento USB do Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Ligou o telefone ao computador através de USB. Seleccione o botão abaixo se pretender copiar ficheiros entre o computador e o cartão SD do Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activar armazenamento USB"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Existe um problema ao utilizar o cartão SD para armazenamento USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Existe um problema ao utilizar o armazenamento USB para o armazenamento em massa USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Existe um problema ao utilizar o cartão SD para armazenamento em massa USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Ligado através de USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Seleccione para copiar ficheiro para/do seu computador."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Desactivar armazenamento USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Opte por desactivar o armazenamento USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"O armazenamento USB está a ser utilizado"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Antes de desactivar o armazenamento USB, certifique-se de que desinstalou (\"ejectou\") o cartão SD do Android do computador."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Antes de desactivar o armazenamento USB, certifique-se de que desmontou (\"ejectou\") o armazenamento USB do Android do computador."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Antes de desactivar o armazenamento USB, certifique-se de que desinstalou (\"ejectou\") o cartão SD do Android do computador."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Desactivar armazenamento USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Ocorreu um problema ao desactivar o armazenamento USB. Confirme se desinstalou o anfitrião USB e, em seguida, tente novamente."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Activar armazenamento USB"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se activar o armazenamento USB, algumas aplicações que estiver a utilizar serão paradas e poderão ficar indisponíveis até desactivar o armazenamento USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Falha na operação USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formatar cartão SD"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Tem a certeza de que pretende formatar o cartão SD? Perder-se-ão todos os dados no cartão."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar armaz. USB"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar cartão SD"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatar armazenamento USB e apagar todos os ficheiros armazenados? Não é possível reverter a acção!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Tem a certeza de que pretende formatar o cartão SD? Perder-se-ão todos os dados no cartão."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatar"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB ligada"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Seleccione para desactivar depuração USB."</string>
@@ -826,18 +831,29 @@
     <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>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"A preparar cartão SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Preparar armazenamento USB"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"A preparar cartão SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"A verificar a presença de erros."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Cartão SD vazio"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"Cartão SD vazio ou sistema de ficheiros não suportado."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Cartão SD danificado"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"Cartão SD danificado. Poderá ser necessário reformatá-lo."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"Cartão SD removido de forma inesperada"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Desmonte o cartão SD antes de retirá-lo para evitar a perda de dados."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"É seguro retirar o cartão SD"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Pode remover o cartão SD com segurança."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Cartão SD removido"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"Cartão SD removido. Insira um novo cartão."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Armazenamento USB vazio"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Cartão SD vazio"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"O armazenamento USB está vazio ou tem um sistema de ficheiros não suportado."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Cartão SD vazio ou sistema de ficheiros não suportado."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Armazenamento USB danificado"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Cartão SD danificado"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"O armazenamento USB está danificado. Poderá ser necessário reformatá-lo."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Cartão SD danificado. Poderá ser necessário reformatá-lo."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Armaz. USB removido inesperad."</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Cartão SD removido de forma inesperada"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desmonte o armazenamento USB antes de removê-lo para evitar a perda de dados."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desmonte o cartão SD antes de retirá-lo para evitar a perda de dados."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Seguro remover armaz. USB"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"É seguro retirar o cartão SD"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Pode remover o armazenamento USB com segurança."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Pode remover o cartão SD com segurança."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Armazenamento USB removido"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Cartão SD removido"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"O armazenamento USB foi removido. Insira um novo suporte de dados."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Cartão SD removido. Insira um novo cartão."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nenhuma actividade correspondente encontrada"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar estatísticas de utilização de componentes"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Permite a modificação de estatísticas de utilização de componentes recolhidas. Não se destina a utilização por aplicações normais."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 correspondência"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"A desmontar armazenamento USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"A desmontar cartão SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"A apagar armazenamento USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"A apagar cartão SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Falha ao apagar o armazenamento USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Falha ao apagar o cartão SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"O cartão SD foi removido antes de ser desmontado."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"O armazenamento USB está actualmente a ser verificado."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"O cartão SD está actualmente a ser verificado."</string>
+    <string name="media_removed" msgid="7001526905057952097">"O cartão SD foi removido."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"O armazenamento USB está actualmente a ser utilizado por um computador."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"O cartão SD está actualmente a ser utilizado por um computador."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Suporte de dados externo em estado desconhecido."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index ee038c3..4af491a 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Desligar"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Encerrando…"</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"O seu telefone será desligado."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Nenhum aplicativo recente."</string>
     <string name="global_actions" msgid="2406416831541615258">"Opções do telefone"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Ferramentas de desenvolvimento"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Recursos necessários apenas para desenvolvedores de aplicativo."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Armazenamento"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Acessar o cartão SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Acessa o armazenamento USB."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Acessar o cartão SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar a barra de status"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permite que o aplicativo desative a barra de status ou adicione e remova ícones do sistema."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"barra de status"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Permite que um aplicativo libere o espaço de armazenamento do telefone excluindo arquivos no diretório de cache do aplicativo. O acesso é normalmente muito restrito para o processo do sistema."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Mover recursos do aplicativo"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Permite que um aplicativo mova os recursos do aplicativo da mídia interna para a externa e vice-versa."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"ler dados de registro de informações confidenciais"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Permite que um aplicativo leia os diversos arquivos de registro do sistema. Isso permite que ele descubra informações gerais sobre o que você está fazendo com o telefone, inclusive possíveis informações pessoais ou privadas."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"ler/gravar em recursos pertencentes ao diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Permite que um aplicativo leia e grave em qualquer recurso que pertença ao grupo de diagnósticos; por exemplo, arquivos em /dev. Isso possivelmente pode afetar a estabilidade e a segurança do sistema. Isso deve ser usado APENAS para diagnósticos específicos do hardware realizados pelo fabricante ou pelo operador."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"ativar ou desativar os componentes do aplicativo"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Permite que o aplicativo monte e desmonte arquivos de sistema para armazenamento removível."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatar armazenamento externo"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Permite que o aplicativo formate o armazenamento removível."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"obter informações sobre o armazenamento seguro"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Permite que o aplicativo obtenha informações sobre armazenamento seguro."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"criar armazenamento seguro"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Permite que o aplicativo crie um armazenamento seguro."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"destrói o armazenamento seguro"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Permite que o aplicativo destrua o armazenamento seguro."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"conectar/desconectar armazenamento seguro"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Permite que o aplicativo conecte/desconecte o armazenamento seguro."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"renomear o armazenamento seguro"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Permite que o aplicativo renomeie o armazenamento seguro."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"obter informações sobre o armazenamento interno"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Permite que o aplicativo obtenha informações sobre armazenamento interno."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"criar armazenamento interno"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Permite que o aplicativo crie um armazenamento interno."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"destruir armazenamento interno"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permite que o aplicativo destrua o armazenamento interno."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"conectar/desconectar armazenamento interno"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Permite que o aplicativo conecte/desconecte o armazenamento interno."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"renomear armazenamento interno"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permite que o aplicativo renomeie o armazenamento interno."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"controlar o vibrador"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permite que o aplicativo controle o vibrador."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controlar lanterna"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Permite que um aplicativo configure o telefone Bluetooth local, descubra e pareie com dispositivos remotos."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"criar conexões Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Permite que um aplicativo veja a configuração do telefone Bluetooth local e que possa fazer e aceitar conexões com dispositivos pareados."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"controlar a comunicação a curta distância"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Permite que um aplicativo se comunique com tags, cartões e leitores de comunicação a curta distância (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"desativar o bloqueio de teclas"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite que um aplicativo desative o bloqueio de teclas e qualquer segurança por senha associada. Um exemplo legítimo disso é a desativação do bloqueio de teclas pelo telefone ao receber uma chamada e a reativação do bloqueio quando a chamada é finalizada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler as configurações de sincronização"</string>
@@ -420,22 +423,25 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Permite que um aplicativo leia quaisquer palavras, nomes e frases particulares armazenados pelo usuário no dicionário do usuário."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"gravar no dicionário definido pelo usuário"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permite que um aplicativo grave novas palavras no dicionário do usuário."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"modificar/excluir conteúdo do cartão SD"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Permite que um aplicativo grave no cartão SD."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modificar/excluir cont. USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/excluir conteúdo do cartão SD"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Perm. aplic. grave arm. USB."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Permite que um aplicativo grave no cartão SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"acessar o sistema de arquivos de cache"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que um aplicativo leia e grave no sistema de arquivos de cache."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Limitar senha"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Restringe os tipos de senha que você tem permissão de usar."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Exibir tentativas de login"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Monitora as tentativas malsucedidas de login no aparelho para executar alguma ação."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Redefinir senha"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Força a sua senha para um novo valor, exigindo que o administrador a forneça antes que você possa fazer login."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Forçar bloqueio"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Controla o bloqueio do aparelho, exigindo que a senha seja digitada novamente."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"fazer/receber chamadas pela internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Permite que um aplicativo use o serviço SIP para fazer/receber chamadas pela internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controla o tamanho e os caracteres permitidos nas senhas de desbloqueio de tela"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitora o número de senhas incorretas inseridas ao desbloquear a tela e bloqueia o telefone ou apaga todos os dados do telefone se muitas senhas incorretas forem inseridas"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Alterar a senha para desbloqueio da tela"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Altera a senha para desbloqueio da tela"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloquear a tela"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Controla como e quando a tela é bloqueada"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Apagar todos os dados"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Execute uma redefinição de fábrica, excluindo todos os seus dados sem qualquer confirmação."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Apaga os dados do telefone sem aviso, executando uma redefinição da configuração original"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir o proxy global do dispositivo"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Configura o proxy global do dispositivo para ser usado enquanto a política estiver ativada. Somente o primeiro administrador do dispositivo pode configurar um verdadeiro proxy global."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Residencial"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Comercial"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Outros"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Personalizado"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalizado"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Página inicial"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Comercial"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Outros"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Digite o código PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Digite a senha para desbloquear"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Digite o PIN para desbloquear"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Dica: toque duas vezes para aumentar e diminuir o zoom."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Preencher automaticamente este formulário"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Permite que um aplicativo modifique o histórico ou os favoritos do Navegador armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar os dados do seu Navegador."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"definir alarme no despertador"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que o aplicativo defina um alarme em um aplicativo de despertador instalado. Talvez alguns aplicativos de despertador não implementem esse recurso."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifique as permissões de geolocalização do seu navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que um aplicativo modifique as permissões de geolocalização do navegador. Aplicativos maliciosos podem usar isso para permitir o envio de informações de localização a sites arbitrários."</string>
     <string name="save_password_message" msgid="767344687139195790">"Deseja que o navegador lembre desta senha?"</string>
@@ -659,7 +662,7 @@
   </plurals>
   <plurals name="abbrev_num_seconds_ago">
     <item quantity="one" msgid="1849036840200069118">"1 seg. atrás"</item>
-    <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> segundos\n  atrás"</item>
+    <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> segundos   atrás"</item>
   </plurals>
   <plurals name="abbrev_num_minutes_ago">
     <item quantity="one" msgid="6361490147113871545">"1 minuto atrás"</item>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Forçar fechamento"</string>
     <string name="report" msgid="4060218260984795706">"Informar"</string>
     <string name="wait" msgid="7147118217226317732">"Aguardar"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Aplicativo redirecionado"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> não está em execução."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> foi iniciado."</string>
     <string name="smv_application" msgid="295583804361236288">"O aplicativo <xliff:g id="APPLICATION">%1$s</xliff:g> (processo <xliff:g id="PROCESS">%2$s</xliff:g>) violou a política StrictMode imposta automaticamente."</string>
     <string name="smv_process" msgid="5120397012047462446">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> violou a política StrictMode imposta automaticamente."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar todas"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Armazenamento USB em massa"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Conectado por USB"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Você conectou o telefone ao computador via USB. Selecione o botão abaixo se quiser copiar arquivos entre o computador e o cartão SD do seu Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Você conectou o telefone ao computador via USB. Selecione o botão abaixo se quiser copiar arquivos entre seu computador e o armazenamento USB do Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Você conectou o telefone ao computador via USB. Selecione o botão abaixo se quiser copiar arquivos entre o computador e o cartão SD do seu Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Ativar o armazenamento USB"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Há um problema com o uso do seu cartão SD para armazenamento USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Há um problema com o uso do seu armazenamento USB para armazenamento USB em massa."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Há um problema com o uso do seu cartão SD para armazenamento USB em massa."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Conectado por USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Selecione para copiar arquivos para/do seu computador."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Desativar o armazenamento USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Selecione para desativar o armazenamento USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Armazenamento USB em uso"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Antes de desativar o armazenamento USB, verifique se desconectou (“ejetou”) o cartão SD do Android do computador."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Antes de desativar o armazenamento USB, verifique se desconectou (“ejetou”) o armazenamento USB do Android do computador."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Antes de desativar o armazenamento USB, verifique se desconectou (“ejetou”) o cartão SD do Android do computador."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Desativar o armazenamento USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Houve um problema ao desativar o armazenamento USB. Verifique se desconectou o host USB e tente novamente."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Ativar o armazenamento USB"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se você ativar o armazenamento USB, alguns aplicativos que estão em uso serão interrompidos e poderão não estar disponíveis até você desativar o armazenamento USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Falha de operação de USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formatar cartão SD"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Tem certeza de que deseja formatar o cartão SD? Todos os dados no seu cartão serão perdidos."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar armaz. USB"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar cartão SD"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatar o armazenamento USB, apagando todos os arquivos armazenados? A ação não pode ser revertida!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Tem certeza de que deseja formatar o cartão SD? Todos os dados no seu cartão serão perdidos."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatar"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Selecione para desativar a depuração USB."</string>
@@ -826,18 +831,29 @@
     <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>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Preparando o cartão SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Preparando armazenamento USB"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Preparando o cartão SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Procurando erros."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Cartão SD em branco"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"Cartão SD vazio ou com sistema de arquivos incompatível."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Cartão SD danificado"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"O cartão SD está danificado. Talvez seja necessário reformatá-lo."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"Cartão SD removido inesperadamente."</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Desmonte o cartão SD antes da remoção para evitar a perda de dados."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"O cartão SD já pode ser removido com segurança."</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Você pode remover o cartão SD com segurança."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Cartão SD removido"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"Cartão SD removido. Insira um novo."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Armazenamento USB vazio"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Cartão SD em branco"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"O armazenamento USB está vazio ou possui sistema de arquivos incompatível."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Cartão SD vazio ou com sistema de arquivos incompatível."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Armazenamento USB danificado"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Cartão SD danificado"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"O armazenamento USB está danificado. Talvez seja necessário reformatá-lo."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"O cartão SD está danificado. Talvez seja necessário reformatá-lo."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Armaz. USB remov. inesperad."</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Cartão SD removido inesperadamente."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desconecte o armazenamento USB antes da remoção para evitar a perda de dados."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desmonte o cartão SD antes da remoção para evitar a perda de dados."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"É seguro remover armaz. USB"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"O cartão SD já pode ser removido com segurança."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Você pode remover com segurança o armazenamento USB."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Você pode remover o cartão SD com segurança."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Armazenamento USB removido"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Cartão SD removido"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Armazenamento USB removido. Insira nova mídia."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Cartão SD removido. Insira um novo."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nenhum atividade correspondente foi encontrada"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"atualizar estatísticas de uso do componente"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Permite a modificação das estatísticas de uso do componente coletadas. Não deve ser usado por aplicativos normais."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"Uma correspondência"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Desconectando armazenamento USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Desconectando cartão SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Apagando o armazenamento USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Apagando cartão SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Falha ao apagar o armazenamento USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Falha ao apagar o cartão SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"O cartão SD foi removido antes de ser desconectado."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"O armazenamento USB está sendo verificado no momento."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"O cartão SD está sendo verificado no momento."</string>
+    <string name="media_removed" msgid="7001526905057952097">"O cartão SD foi removido."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"O armazenamento USB está em uso por um computador no momento."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"O cartão SD está em uso por um computador no momento."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Mídia externa em estado desconhecido."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index f040bd0..91df5bc 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Выключение"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Выключение..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Телефон будет выключен."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Недавние"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Нет последних приложений."</string>
     <string name="global_actions" msgid="2406416831541615258">"Параметры телефона"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Инструменты разработки"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Функции, необходимые только разработчикам приложений."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Память"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Доступ к SD-карте."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Доступ к USB-накопителю."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Доступ к SD-карте."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"отключать или изменять строку состояния"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Позволяет приложению отключать строку состояния или добавлять/удалять системные значки."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"строка состояния"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Позволяет приложению освобождать память телефона с помощью удаления файлов из каталога кэша приложений. Обычно это разрешается только системным процессам."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Перемещать ресурсы приложения"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Позволяет приложению перемещать ресурсы приложения с внутренних на внешние носители и наоборот."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"считывать конфиденциальные данные журнала"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Позволяет приложению считывать информацию из различных журналов системы. Приложение может получать сведения о работе пользователя с телефоном, которые могут содержать личную или конфиденциальную информацию."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"считывать/записывать данные в ресурсы, принадлежащие группе диагностики"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Позволяет приложению считывать и записывать данные в любые ресурсы, принадлежащие группе диагностики (например, файлы в каталоге /dev). Это может повлиять на стабильность и безопасность системы. Эта возможность может быть использована ТОЛЬКО производителем или оператором для диагностики аппаратного обеспечения."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"включать или отключать компоненты приложения"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Позволяет приложению монтировать и удалять файловые системы съемных носителей."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"форматировать внешний накопитель"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Позволяет приложению форматировать съемный накопитель."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"получать сведения о защищенном хранилище"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Позволяет программе получать сведения о защищенном хранилище."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"создать защищенное хранилище"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Позволяет программам создавать защищенные хранилища."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"удалять защищенное хранилище"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Позволяет программе удалять защищенные хранилища."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"подключать / отключать защищенное хранилище"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Позволяет программе подключать и отключать защищенные хранилища."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"переименовать защищенное хранилище"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Позволяет программам переименовывать защищенные хранилища."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"получать сведения о внутреннем накопителе"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Позволяет приложению получать сведения о внутреннем накопителе."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"создавать внутренний накопитель"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Позволяет приложениям создавать внутренний накопитель."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"удалять внутренний накопитель"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Позволяет приложению удалять внутренний накопитель."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"подключать/отключать внутренний накопитель"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Позволяет приложению подключать и отключать внутренний накопитель."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"переименовывать внутренний накопитель"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Позволяет приложениям переименовывать внутренний накопитель."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"управлять вибровызовом"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Позволяет приложению управлять виброзвонком."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"управлять вспышкой"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Позволяет приложению настраивать локальный телефон Bluetooth, обнаруживать и выполнять сопряжение удаленных устройств."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"создавать подключения Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Позволяет приложению просматривать конфигурацию локального телефона Bluetooth, создавать подключения с сопряженными устройствами."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"управлять радиосвязью ближнего действия"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Позволяет приложению обмениваться данными с метками, картами и считывателями через радиосвязь ближнего действия (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"отключать блокировку клавиатуры"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Позволяет приложению отключить блокировку клавиатуры и другие функции защиты паролем. Примером допустимого использования этой функции является отключение блокировки клавиатуры при получении входящего вызова и включение блокировки после завершения разговора."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"считывать настройки синхронизации"</string>
@@ -420,23 +423,26 @@
     <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="permdesc_sdcardWrite" msgid="6643963204976471878">"Разрешает приложению запись на SD-карту"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"изменять и удалять содержимое USB-накопителя"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"изменять/удалять содержимое SD-карты"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Разрешает приложению запись на USB-накопитель."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Разрешает приложению запись на SD-карту"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"получать доступ к кэшу файловой системы"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Разрешает программам доступ для записи и чтения к кэшу файловой системы."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Ограничить пароль"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Ограничить типы паролей, доступных для использования."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Просмотр попыток входа"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Мониторинг неудачных попыток подключения к устройству для выполнения определенных действий."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Сбросить пароль"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Принудительно изменить пароль, который администратор должен будет сообщить вам, чтобы вы смогли выполнить вход."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Принудительная блокировка"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Управление блокировкой устройства, требующей ввода пароля."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"совершать и принимать интернет-вызовы"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Позволяет приложению использовать службу SIP для интернет-вызовов."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Правила выбора паролей"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Контролировать длину и символы при вводе паролей для снятия блокировки экрана"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Отслеживать попытки снятия блокировки экрана"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Отслеживать количество неверно введенных паролей для снятия блокировки экрана и блокировать телефон либо уничтожить все данные на нем, если было введено слишком много неверных паролей"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Изменять пароль для снятия блокировки экрана"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Изменять пароль для снятия блокировки экрана"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Блокировать экран"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Контролировать способ и время блокировки экрана"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Удалить все данные"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Выполнить сброс к начальным настройкам с удалением всех данных без запроса подтверждения."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Настройте глобальный прокси-сервер устройства, который будет использоваться при активной политике. Глобальный прокси-сервер должен настроить администратор первого устройства."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Уничтожить все данные на телефоне без предупреждения путем сброса настроек"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Глобальный прокси-сервер"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Настройте глобальный прокси-сервер устройства, который будет использоваться при активной политике. Глобальный прокси-сервер должен настроить первый администратор устройства."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Домашний"</item>
     <item msgid="869923650527136615">"Мобильный"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Работа"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Другое"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Создать свой ярлык"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Особый"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Домашний"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Рабочий"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Другой"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Введите PIN-код"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Введите пароль для разблокировки"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Введите PIN-код для разблокировки"</string>
@@ -570,7 +572,7 @@
     <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_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Количество неудачных попыток ввода пароля: <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Повторите попытку через <xliff:g id="NUMBER_1">%d</xliff:g> с."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Количество неудачных попыток ввода PIN-кода: <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\n" Повторите попытку через <xliff:g id="NUMBER_2">%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>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Повторите попытку через <xliff:g id="NUMBER">%d</xliff:g> с."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Забыли графический ключ?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Снятие блокировки аккаунта"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Совет: нажмите дважды, чтобы увеличить и уменьшить масштаб."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Заполнить форму автоматически"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"считывать историю и закладки браузера"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Разрешает приложению считывать все URL, посещенные браузером, и все его закладки."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"записывать историю и закладки браузера"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Разрешает приложению изменять историю и закладки браузера, сохраненные в вашем телефоне. Вредоносное ПО может пользоваться этим, чтобы стирать или изменять данные вашего браузера."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"настраивать сигнал будильника"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Позволяет настраивать сигнал установленного приложения будильника. Для некоторых приложений будильника эта функция может быть недоступна."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Изменить разрешения браузера для доступа к географическому местоположению"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Позволяет программе изменять разрешения браузера для доступа к географическому положению. Вредоносные программы могут пользоваться этим для отправки информации о местоположении на некоторые сайты."</string>
     <string name="save_password_message" msgid="767344687139195790">"Вы хотите, чтобы браузер запомнил этот пароль?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Закрыть"</string>
     <string name="report" msgid="4060218260984795706">"Отчет"</string>
     <string name="wait" msgid="7147118217226317732">"Подождать"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Приложение перенаправлено"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> выполняется."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Изначально было запущено приложение <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="smv_application" msgid="295583804361236288">"Приложение <xliff:g id="APPLICATION">%1$s</xliff:g> (процесс <xliff:g id="PROCESS">%2$s</xliff:g>) нарушило собственную политику StrictMode."</string>
     <string name="smv_process" msgid="5120397012047462446">"Процесс <xliff:g id="PROCESS">%1$s</xliff:g> нарушил собственную политику StrictMode."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Приложение <xliff:g id="APP">%1$s</xliff:g> запущено"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Показать все"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Запоминающее устройство USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-подключение установлено"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Телефон подключен к компьютеру через порт USB. Нажмите кнопку ниже, если необходимо копировать файлы с компьютера на SD-карту устройства Android (или наоборот)."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Телефон подключен к компьютеру через порт USB. Для копирования файлов между компьютером и USB-накопителем Android нажмите кнопку ниже."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Телефон подключен к компьютеру через порт USB. Нажмите кнопку ниже, если необходимо копировать файлы с компьютера на SD-карту устройства Android (или наоборот)."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Включить USB-накопитель"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"При использовании SD-карты как USB-накопителя возникла неполадка."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"При использовании USB-накопителя в качестве запоминающего устройства USB возникла неполадка."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"При использовании SD-карты в качестве запоминающего устройства USB возникла неполадка."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB-подключение установлено"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Выберите копирование файлов на компьютер или с компьютера."</string>
-    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Выключить USB-накопитель"</string>
-    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Выберите, чтобы выключить USB-накопитель."</string>
+    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Отключить USB-накопитель"</string>
+    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Нажмите, чтобы отключить USB-накопитель."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-накопитель используется"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Перед отключением USB-накопителя убедитесь, что SD-карта устройства Android была отключена от компьютера."</string>
-    <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Выключить USB-накопитель"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Перед отключением USB-накопителя убедитесь, что USB-накопитель Android был отключен от компьютера."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Перед отключением USB-накопителя убедитесь, что SD-карта устройства Android была отключена от компьютера."</string>
+    <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Отключить USB-накопитель"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"При выключении USB-накопителя произошла неполадка. Убедитесь, что USB-хост отключен, и повторите попытку."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Включение USB-накопителя"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"При включении USB-накопителя некоторые используемые приложения могут прекратить работу и оставаться недоступными до отключения USB-накопителя."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Сбой операции USB-подключения"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"ОК"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Очистить SD-карту"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Отформатировать карту SD? Все данные, находящиеся на карте, будут уничтожены."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирование"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Очистить SD-карту"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Форматирование USB-накопителя безвозвратно удалит все файлы на нем! Продолжить?"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Отформатировать карту SD? Все данные, находящиеся на карте, будут уничтожены."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Формат"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Отладка по USB разрешена"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Нажмите, чтобы отключить отладку USB."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"варианты"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Подготовка карты SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Подготовка USB-накопителя"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Подготовка карты SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Проверка ошибок."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Пустая карта SD"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"SD-карта пуста или использует неподдерживаемую файловую систему"</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Поврежденная карта SD"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"SD-карта повреждена. Попробуйте отформатировать ее."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"Карта SD неожиданно извлечена"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Перед извлечением карты SD отключите ее во избежание потери данных."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"Безопасное удаление карты SD"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Можно безопасно извлечь SD-карту."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Отсутствует карта SD"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"SD-карта извлечена. Вставьте новую карту."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Пустой USB-накопитель"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Пустая карта SD"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"На USB-накопителе нет данных или его файловая система не поддерживается."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-карта пуста или использует неподдерживаемую файловую систему"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB-накопитель поврежден"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Поврежденная карта SD"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB-накопитель поврежден. Попробуйте отформатировать его."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD-карта повреждена. Попробуйте отформатировать ее."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-накопитель неожиданно отключен"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Карта SD неожиданно извлечена"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Перед извлечением USB-накопителя отключите его во избежание потери данных."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Перед извлечением карты SD отключите ее во избежание потери данных."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB-накопитель можно отключить"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Безопасное удаление карты SD"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Теперь USB-накопитель может быть безопасно отключен."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Можно безопасно извлечь SD-карту."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB-накопитель отключен"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Отсутствует карта SD"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB-накопитель отключен. Вставьте другой накопитель."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-карта извлечена. Вставьте новую карту."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Подходящих действий не найдено"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"обновлять статистику использования компонентов"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Позволяет изменять собранную статистику использования компонентов. Не предназначено для использования обычными приложениями."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 совпадение"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> из <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Отключение USB-накопителя..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Отключение SD-карты..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Очистка USB-накопителя..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Очистка SD-карты..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Не удалось очистить USB-накопитель."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Не удалось очистить SD-карту."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD-карта была извлечена до отключения."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB-накопитель проверяется."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Выполняется проверка SD-карты."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD-карта была отключена."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Сейчас USB-накопитель используется компьютером."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Сейчас SD-карта используется компьютером."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Неизвестно состояние внешнего носителя."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 418a8e6..b8b6f64 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Stäng av"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Avslutar…"</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Din telefon stängs av."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"Senaste"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Inga nya program."</string>
     <string name="global_actions" msgid="2406416831541615258">"Telefonalternativ"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Utvecklingsverktyg"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funktioner som endast behövs för programutvecklare."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Lagring"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"Få åtkomst till SD-kortet."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Få åtkomst till USB-enheten."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Få åtkomst till SD-kortet."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"inaktivera eller ändra statusfält"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Tillåter att programmet inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"statusfält"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Tillåter att ett program frigör lagringsutrymme i telefonen genom att ta bort filer i programmets katalog för cachelagring. Åtkomst är mycket begränsad, vanligtvis till systemprocesser."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Flytta programresurser"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Tillåter att ett program flyttar programresurser från interna till externa medier och tvärt om."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"läsa känsliga loggdata"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Tillåter att ett program läser från systemets olika loggfiler. Det innebär att programmet kan upptäcka allmän information om vad du gör med telefonen, vilket kan inkludera personlig eller privat information."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"läsa/skriva till resurser som ägs av diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Tillåter att ett program läser och skriver till en resurs som ägs av diag-gruppen; till exempel filer i /dev. Detta kan eventuellt påverka systemets stabilitet och säkerhet. Detta bör ENDAST används av tillverkaren eller operatören för maskinvaruspecifik diagnostik."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"aktivera eller inaktivera programkomponenter"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Tillåter att programmet monterar och demonterar filsystem för flyttbara lagringsmedia."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatera extern lagring"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Tillåter att programmet formaterar flyttbara lagringsmedia."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"få information om säker lagring"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Tillåter att programmet får information om säker lagring."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"skapa säker lagring"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Tillåter att programmet skapar säker lagring."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"förstör säker lagring"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Tillåter att programmet förstör säker lagring."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"montera/avmontera säker lagring"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Tillåter att programmet monterar/avmonterar säker lagring."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"byt namn på säker lagring"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Tillåter att programmet byter namn på säker lagring."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"få information om intern lagring"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Tillåter att appen får information om intern lagring."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"skapa intern lagring"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Tillåter att appen skapar intern lagring."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"förstör intern lagring"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Tillåter att appen förstör intern lagring."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"montera/demontera intern lagring"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Tillåter att appen monterar/demonterar intern lagring."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"byt namn på intern lagring"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Tillåter att appen byter namn på intern lagring."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"kontrollera vibration"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Tillåter att programmet styr vibratorn."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"styra lampa"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Tillåter att ett program konfigurerar den lokala Bluetooth-telefonen samt upptäcker och parkopplar den med fjärranslutna enheter."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"skapa Bluetooth-anslutningar"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Tillåter att ett program ser den lokala Bluetooth-telefonens konfiguration, och skapar och accepterar anslutningar med parkopplade enheter."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"kontrollera närfältskommunikationen"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Tillåter att en app kommunicerar med taggar, kort och läsare för närfältskommunikation (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"inaktivera tangentlås"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Tillåter att ett program inaktiverar tangentlåset och tillhörande lösenordsskydd. Ett exempel på detta är att telefonen inaktiverar tangentlåset vid inkommande samtal och sedan aktiverar det igen när samtalet är avslutat."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"läsa synkroniseringsinställningar"</string>
@@ -420,22 +423,25 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Tillåt att ett program läser alla privata ord, namn och fraser som användaren lagrar i sin ordlista."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"skriva till användardefinierad ordlista"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Tillåter att ett program skriver in nya ord i användarordlistan."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"ändra/ta bort innehåll på SD-kortet"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Tillåter att ett program skriver till SD-kortet."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"ändra/ta bort från USB-enhet"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"ändra/ta bort innehåll på SD-kortet"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Får skriva till USB-enheten."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Tillåter att ett program skriver till SD-kortet."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"åtkomst till cachefilsystemet"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillåter att ett program läser och skriver till cachefilsystemet."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Begränsa lösenord"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Begränsar vilka typer av lösenord som får användas."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Visa inloggningsförsök"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Övervaka misslyckade inloggningsförsök på enheten för att utföra åtgärder."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Återställ lösenord"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Framtvinga ett nytt värde för ditt lösenord. Kräver att administratören tillhandahåller det innan du kan logga in."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Framtvinga låsning"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Kontrollera när enheten låses, vilket kräver att du anger lösenordet igen."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"ringa/ta emot Internetsamtal"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Tillåter att appen använder SIP-tjänsten för att ringa och ta emot Internetsamtal."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Bestäm hur många och vilka tecken som är tillåtna i skärmlåsets lösenord"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Övervaka antalet felaktiga lösenord som angivits för skärmlåset och lås telefonen eller ta bort alla data från telefonen om för många felaktiga försök görs"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Ändra skärmlåsets lösenord"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Ändra skärmlåsets lösenord"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Lås skärmen"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrollera hur och när skärmlåset aktiveras"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Radera alla data"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Återställ fabriksinställningarna och ta bort alla data utan någon bekräftelse."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Ta bort data från telefonen utan förvarning genom att återställa standardinställningarna"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Ange global proxyserver"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Ange vilken global proxyserver som ska användas när policyn är aktiverad. Endast den första enhetsadministratören anger den faktiska globala proxyservern."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hem"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Arbete"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Övrigt"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Anpassad"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Anpassad"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Startsida"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbete"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Övrigt"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ange PIN-kod"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Ange lösenord för att låsa upp"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Ange PIN-kod för att låsa upp"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"Tips! Dubbelklicka om du vill zooma in eller ut."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Autofyll formuläret"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Tillåter att ett program ändrar webbläsarhistoriken och bokmärkena i din telefon. Skadliga program kan använda detta för att ta bort eller ändra data i webbläsaren."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"ställa in alarm i alarmklocka"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Tillåter att programmet ställer in ett alarm i ett installerat alarmprogram. Vissa alarmprogram har inte den här funktionen."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Ändra geografisk plats för webbläsaren"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Tillåter att ett program ändrar webbläsarens behörigheter för geografisk plats. Skadliga program kan använda detta för att tillåta att platsinformation skickas till godtyckliga webbplatser."</string>
     <string name="save_password_message" msgid="767344687139195790">"Vill du att webbläsaren ska komma ihåg lösenordet?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Tvinga fram en stängning"</string>
     <string name="report" msgid="4060218260984795706">"Rapportera"</string>
     <string name="wait" msgid="7147118217226317732">"Vänta"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Programmet omdirigerades"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> körs."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> startades först."</string>
     <string name="smv_application" msgid="295583804361236288">"Programmet <xliff:g id="APPLICATION">%1$s</xliff:g> (processen <xliff:g id="PROCESS">%2$s</xliff:g>) har brutit mot sin egen StrictMode-policy."</string>
     <string name="smv_process" msgid="5120397012047462446">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> har brutit mot sin egen StrictMode-policy."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> körs"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Visa alla"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-masslagring"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-ansluten"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Du har anslutit telefonen till datorn via USB. Välj knappen nedan om du vill kopiera filer mellan datorn och SD-kortet i din Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Du har anslutit telefonen till datorn via USB. Välj knappen nedan om du vill kopiera filer mellan datorn och Android-telefonens USB-lagringsenhet."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Du har anslutit telefonen till datorn via USB. Välj knappen nedan om du vill kopiera filer mellan datorn och SD-kortet i din Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Aktivera USB-lagring"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"Det gick inte att använda ditt SD-kort för USB-lagring."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Det gick inte att använda din USB-lagringsenhet för USB-masslagring."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Det gick inte att använda ditt SD-kort för USB-masslagring."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB-ansluten"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Välj om du vill kopiera filer till/från din dator."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Inaktivera USB-lagring"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Välj om USB-lagring ska inaktiveras."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-lagret används"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"Kontrollera att du har demonterat (\"matat ut\") Android-telefonens SD-kort från datorn, innan du inaktiverar USB-lagring."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Kontrollera att du har demonterat(matat ut) Android-telefonens USB-lagringsenhet från datorn innan du inaktiverar USB-lagring."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Kontrollera att du har demonterat (\"matat ut\") Android-telefonens SD-kort från datorn, innan du inaktiverar USB-lagring."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Inaktivera USB-lagring"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Ett problem uppstod när USB-lagringsplatsen skulle inaktiveras. Kontrollera att USB-värden har demonterats och försök igen."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Aktivera USB-lagring"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Om du aktiverar USB-lagring avbryts några av de program som körs och de kanske inte blir tillgängliga igen förrän du inaktiverar USB-lagring."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-åtgärd misslyckades"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"Formatera SD-kort"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"Vill du formatera SD-kortet? Alla data på ditt kort kommer att gå förlorade."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatera USB-enhet"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatera SD-kort"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatera SD-kort och radera alla filer? Åtgärden kan inte ångras!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Vill du formatera SD-kortet? Alla data på ditt kort kommer att gå förlorade."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-felsökning ansluten"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Välj att inaktivera USB-felsökning."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"Förbereder SD-kort"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Förbereder USB-lagring"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Förbereder SD-kort"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Söker efter fel."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Tomt SD-kort"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"SD-kortet är tomt eller så har det ett filsystem som inte stöds."</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Skadat SD-kort"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"SD-kortet är skadat. Du måste eventuellt formatera om det."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"SD-kort togs oväntat bort"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Demontera SD-kort innan borttagning för att undvika dataförlust."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"Säkert att ta bort SD-kort"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"Det är nu säkert att ta bort SD-kortet."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"Borttaget SD-kort"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"SD-kortet har tagits bort. Sätt i ett nytt."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Tom USB-lagringsenhet"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tomt SD-kort"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB-lagringsenheten är tom eller så har den ett filsystem som inte stöds."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-kortet är tomt eller så har det ett filsystem som inte stöds."</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Skadad USB-lagringsenhet"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Skadat SD-kort"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB-lagringsenheten är skadad. Du måste eventuellt formatera om den."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD-kortet är skadat. Du måste eventuellt formatera om det."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-enheten togs oväntat bort"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-kort togs oväntat bort"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Demontera USB-lagringsenheten före borttagning för att undvika dataförlust."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Demontera SD-kort innan borttagning för att undvika dataförlust."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Säkert att ta bort USB-enhet"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Säkert att ta bort SD-kort"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Det är nu säkert att ta bort USB-lagringsenheten."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Det är nu säkert att ta bort SD-kortet."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB-lagringsenheten togs bort"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Borttaget SD-kort"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB-lagringsenheten har tagits bort. Sätt i en ny."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-kortet har tagits bort. Sätt i ett nytt."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Inga matchande aktiviteter hittades"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"uppdatera statistik över användning av komponenter"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Tillåter att samlad komponentstatistik ändras. Används inte av vanliga program."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 träff"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> av <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Demontera USB-lagringsenhet..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Demonterar SD-kort..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Raderar USB-lagring..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Raderar SD-kort..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Det gick inte att radera USB-lagring"</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Det gick inte att radera SD-kortet."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD-kortet demonterades inte innan det togs bort."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB-lagringsenheten kontrolleras."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SD-kortet kontrolleras."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD-kortet har tagits bort."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB-lagringsenheten används av en dator."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SD-kortet används för närvarande av en dator."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Externa media i okänt tillstånd."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 6ac5b86d..5d3d55d 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"Kapat"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Kapanıyor…"</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"Telefonunuz kapanacak."</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"En Son Görevler"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Hiçbir yeni uygulama yok."</string>
     <string name="global_actions" msgid="2406416831541615258">"Telefon seçenekleri"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Geliştirme araçları"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Yalnızca uygulama geliştiriciler için gerekli özellikler."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Depolama"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"SD karta erişin."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Payl depolama birimine erişin."</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"SD karta erişin."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"durum çubuğunu devre dışı bırak veya değiştir"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Uygulamanın durum çubuğunu devre dışı bırakmasına veya sistem simgeleri ekleyip kaldırmasına izin verir."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"durum çubuğu"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"Uygulamaların uygulama önbelleği dizinindeki dosyaları silerek telefonda yer açmasına izin verir. Erişim genellikle sistem işlemlerine ve yüksek düzeyde kısıtlı olarak verilir."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Uygulama kaynaklarını taşı"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Bir uygulamanın, uygulama kaynaklarını dahili ve harici ortamlar arasında taşımasına olanak tanır."</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"hassas günlük verilerini okuma"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"Bir uygulamanın, sistemin çeşitli günlük dosyalarındaki bilgileri okumasına izin verir. Bu izin, uygulamanın, telefonda yaptıklarınızla ilgili genel bilgileri bulmasına olanak sağlar ve bunlar kişisel ve gizli bilgilerinizi de içerebilir."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"sahibi tanılama olan kaynakları oku/bunlara yaz"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Uygulamanın tanılama grubundaki bir kaynağa ait herhangi bir kaynağı; örneğin /dev içindeki dosyaları okumasına ve bunlara yazmasına izin verir. Bu işlevin sistem kararlılığını ve güvenliğini olumsuz etkileme olasılığı vardır. Üretici veya operatör tarafından YALNIZCA donanıma özgü tanılama için kullanılmalıdır."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"uygulama bileşenlerini etkinleştir veya devre dışı bırak"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Uygulamaların çıkarılabilir depolama birimleri için dosya sistemleri ile bağlantı kurmasına ve bağlantıyı kesmesine izin verir."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"harici depolama birimini biçimlendir"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Uygulamanın çıkarılabilir depolama birimini biçimlendirmesine izin verir."</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"güvenli depolama birimi hakkında bilgi al"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"Uygulamanın güvenli depolama birimi hakkında bilgi almasına izin verir."</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"güvenli depolama birimi oluştur"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"Uygulamanın güvenli depolama birimi oluşturmasına izin verir."</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"güvenli depolama birimini yok et"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"Uygulamanın güvenli depolama birimini yok etmesine izin verir."</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"güvenli depolama birimini ekle / kaldır"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"Uygulamanın güvenli depolama birimini yeniden eklemesine / kaldırmasına izin verir."</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"güvenli depolama birimini yeniden adlandır"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"Uygulamanın güvenli depolama birimini yeniden adlandırmasına izin verir."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"dahili depolama birimi hakkında bilgi al"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Uyg\'nın dahili depl birimi hakkında bilgi almasına izin verir."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"dahili dep brm oluştur"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Uyg\'nın dahili dep brmi oluşturmasına izin verir."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"dahili depolama birimini yok et"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Uyg\'nın dahili dep birmni yok etmesine izin verir."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"dahili dep birm ekle/bağlant kes"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Uyg\'nın dahili dep brmni eklemsn/bağl kesmesine izin verir."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"dahili dep br adını dğş"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Uyg\'nın dahili dep brmnin adını değş izin verir."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"titreşimi denetle"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Uygulamanın titreşimi denetlemesine izin verir."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"flaşı denetle"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Uygulamaların yerel Bluetooth telefonunu yapılandırmasına ve uzak cihazları keşfedip bunlar ile eşleşmesine izin verir."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth bağlantıları oluştur"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Uygulamaların yerel Bluetooth telefonunun yapılandırmasını görüntülemesine ve eşleşilmiş cihazlar ile bağlantı kurup kabul etmesine izin verir."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"Yakın Alan İletişimini denetle"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Bir uyg\'nın Yakın Alan İletişimi etiketleri, kartları ve okuyclr ile iletşm kurmasına izin verir."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"tuş kilidini devre dışı bırak"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Uygulamaların tuş kilidini ve ilgili şifreli güvenlik önlemini devre dışı bırakmasına izin verir. Bunun geçerli bir örneği gelen bir çağrı alındığında tuş kilidinin devre dışı bırakılması, sonra çağrı bittiğinde kilidin yeniden devreye sokulmasıdır."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"senk. ayarlarını oku"</string>
@@ -420,22 +423,25 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Kullanıcının kullanıcı sözlüğünde depolamış olabileceği kişisel kelimeleri, adları ve kelime öbeklerini uygulamaların okumasına izin verir."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"kullanıcı tanımlı sözlüğe yaz"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Uygulamaların kullanıcı sözlüğüne yeni kelimeler yazmasına izin verir."</string>
-    <string name="permlab_sdcardWrite" msgid="8079403759001777291">"SD kart içeriklerini değiştir/sil"</string>
-    <string name="permdesc_sdcardWrite" msgid="6643963204976471878">"Bir uygulamaya SD karta yazma izni verir."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"USB dep birm içeriğini dğş/sil"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"SD kart içeriklerini değiştir/sil"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Uygulamanın USB dep birimine yazmasına izni verir."</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Bir uygulamaya SD karta yazma izni verir."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"önbellek dosya sistemine eriş"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Bir uygulamanın önbellek dosya sisteminde okuma yazma yapmasına izin verir."</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"Şifreyi sınırla"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"Kullanmanıza izin verilen şifre türlerini sınırlayın."</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"Oturum açma denemelerini izle"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"Bir işlem gerçekleştirmek için cihazdaki başarısız oturum açma girişimlerini izleyin."</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"Şifre sıfırlama"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"Şifrenizi yeni bir değer alması için zorlayın. Giriş yapabilmeniz için yöneticinin size yeni bir değer sağlamasını gerekecektir."</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"Kilitlemeye zorlama"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"Cihaz kilitlendiğinde, şifresini yeniden girmenizi gerektiren denetim."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"İnternet çağrılar yap/alma"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Uygulamanın İnternet çağ yapmak/almak için SIP hiz kullanmasına izin verir."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ekran kilidini açma şifrelerinde izin verilen uzunluğu ve karakterleri kontrol edin"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Ekran kilidi açılırken girilen yanlış şifre sayısını izler ve çok fazla sayıda yanlış şifre girilirse telefonu kilitler veya telefondaki tüm verileri siler"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Ekran kilidini açma şifresini değiştir"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Ekran kilidini açma şifresini değiştirin"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Ekranı kilitle"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Ekranın nasıl ve ne zaman kilitlendiğini kontrol edin"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Tüm verileri sil"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"Tüm verilerinizi onay olmadan silmek için fabrika ayarlarına sıfırlayın."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek telefondaki verileri uyarıda bulunmadan silin"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Cihaz genelinde geçerli proxy\'i ayarla"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Politika etkin olduğunda kullanılacak cihaz genelinde geçerli proxy\'yi ayarlayın. Etkin genel proxy\'yi yalnızca ilk cihaz yöneticisi ayarlar."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Ev"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"İş"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Diğer"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Özel"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Özel"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Ev"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"İş"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Diğer"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN kodunu gir"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Kilidi açmak için şifreyi girin"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Kilidi açmak için PIN\'i girin"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"İpucu: Yakınlaştırmak ve uzaklaştırmak için iki kez hafifçe vurun."</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"Bu formu otomatik doldur"</string>
     <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>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Uygulamaya telefonunuzda depolanan Tarayıcı geçmişini veya favorileri değiştirme izni verir. Kötü amaçlı uygulamalar bunu Tarayıcı verilerinizi silmek veya değiştirmek için kullanabilir."</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"çalar saatte alarm ayarla"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Uygulamanın yüklü bir çalar saat uygulamasında bir alarm ayarlamasına izin verir. Bazı çalar saat uygulamaları bu özelliği kullanmayabilir."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Tarayıcı\'nın coğrafi konum izinlerini değiştir"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Bir uygulamanın, Tarayıcı\'nın coğrafi konum izinlerini değiştirmesine izin verir. Kötü amaçlı uygulamalar, bu özelliği konum bilgilerini rastgele web sitelerine göndermek için kullanabilir."</string>
     <string name="save_password_message" msgid="767344687139195790">"Tarayıcının bu şifreyi anımsamasını istiyor musunuz?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"Kapanmaya zorla"</string>
     <string name="report" msgid="4060218260984795706">"Rapor"</string>
     <string name="wait" msgid="7147118217226317732">"Bekle"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Uygulama yönlendirildi"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> şimdi çalışıyor."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"İlk olarak <xliff:g id="APP_NAME">%1$s</xliff:g> başlatıldı."</string>
     <string name="smv_application" msgid="295583804361236288">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması (<xliff:g id="PROCESS">%2$s</xliff:g> işlemi) kendiliğinden uyguladığı StrictMode politikasını ihlal etti."</string>
     <string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> işlemi kendiliğinden uyguladığı StrictMode politikasını ihlal etti."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> çalışıyor"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Tümünü göster"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB Yığın Depolama"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB bağlandı"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"Telefonunuzu USB ile bilgisayarınıza bağladınız. Bilgisayarınız ile Android\'inizin SD kartı arasında dosya kopyalamak istiyorsanız aşağıdaki düğmeyi seçin."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"Telefonunuzu USB ile bilgisayarınıza bağladınız. Bilgisayarınız ile Android\'inizin USB depolama birimi arasında dosya kopyalamak istiyorsanız aşağıdaki düğmeyi seçin."</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Telefonunuzu USB ile bilgisayarınıza bağladınız. Bilgisayarınız ile Android\'inizin SD kartı arasında dosya kopyalamak istiyorsanız aşağıdaki düğmeyi seçin."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USB depolama birimini aç"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"SD kartınızı USB depolama birimi için kullanmada bir sorun var."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"USB depolama biriminizi USB yığın depolama amaçlı kullanmayla ilgili bir sorun var."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"SD kartınızı USB yığın dep br amaçlı kullanmada sorun var."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB bağlandı"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Bilgisayarınıza/bilgisayarınızdan dosya kopyalamak için seçin."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB depolama birimini kapat"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"USB depolama birimini kapatmak için seçin."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB depolama birimi kullanılıyor"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"USB depolama birimini kapatmadan önce Android SD kartını bilgisayarınızdan kaldırdığınızdan (\"çıkardığınızdan\") emin olun."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"USB depolama birimini kapatmadan önce Android\'inizin USB depolama biriminin bilgisayarınızla olan bağlantısını kestiğinizden (\"çıkardığınızdan\") emin olun."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"USB depolama birimini kapatmadan önce Android SD kartını bilgisayarınızdan kaldırdığınızdan (\"çıkardığınızdan\") emin olun."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB depolama birimini kapat"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"USB depolama birimini kapatırken bir sorun oluştu. USB ana makinesini kaldırdığınızdan emin olun ve daha sonra tekrar deneyin."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"USB depolama birimini aç"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB depolama birimini açarsanız, kullanmakta olduğunuz bazı uygulamalar durur ve USB depolama birimi kapatılıncaya kadar kullanılamayabilir."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB işlemi başarısız oldu"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Tamam"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"SD kartı biçimlendir"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"SD kartı biçimlendirmek istediğinizden emin misiniz? Kartınızdaki tüm veriler yok olacak."</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB dep br biçimlndr"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD kartı biçimlendir"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB depolama birimi biçimlendirilsin mi? Depolama biriminde saklanan tüm dosyalar silinir. İşlem geri alınamaz!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"SD kartı biçimlendirmek istediğinizden emin misiniz? Kartınızdaki tüm veriler yok olacak."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Biçimlendir"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB hata ayıklaması bağlandı"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"USB hata ayıklamasını devre dışı bırakmak için tıklayın."</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"adaylar"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"SD kart hazırlanıyor"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"USB depolm birimi hazırlanıyor"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD kart hazırlanıyor"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Hatalar denetleniyor."</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"Boş SD kart"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"SD kart boş veya desteklenmeyen dosya sistemi içeriyor"</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"Hasarlı SD kart"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"SD kart zarar gördü. Yeniden biçimlendirmeniz gerekebilir."</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"SD kart beklenmedik biçimde çıkarıldı"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"Veri kaybından kaçınmak için SD kartı çıkarmadan önce bağlantısını kesin."</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"SD kart güvenle çıkarılabilir"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"SD kartı güvenle kaldırabilirsiniz."</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"SD kart çıkarılmış"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"SD kart çıkarıldı. Yeni bir SD kart takın."</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Boş USB depolama birimi"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Boş SD kart"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB depolama birimi boş veya desteklenmeyen bir dosya sistemine sahip."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD kart boş veya desteklenmeyen dosya sistemi içeriyor"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB depolm birimi zarar görmüş"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Hasarlı SD kart"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB depolama birimi zarar görmüş. Yeniden biçimlendirmeniz gerekebilir."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD kart zarar gördü. Yeniden biçimlendirmeniz gerekebilir."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB dep br bklnmd şekl çıkarld"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD kart beklenmedik biçimde çıkarıldı"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Veri kaybı olmaması için çıkarmadan önce USB depolama biriminin bağlantısını kesin."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Veri kaybından kaçınmak için SD kartı çıkarmadan önce bağlantısını kesin."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB depl birm güvenle çıkrlblr"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD kart güvenle çıkarılabilir"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"USB depolama birimini güvenli bir şekilde çıkarabilirsiniz."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"SD kartı güvenle kaldırabilirsiniz."</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB depolama birimi çıkarıldı"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD kart çıkarılmış"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB depolama birimi çıkarıldı. Yeni medyayı takın."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD kart çıkarıldı. Yeni bir SD kart takın."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Eşleşen hiçbir etkinlik bulunamadı"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"bileşen kullanım istatistiklerini güncelle"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Toplanmış bileşen istatistiklerinin değiştirilmesine izin verir. Normal uygulamalarda kullanılmamalıdır."</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 eşleşme"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> / <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"USB depolama biriminin bağlantısı kesiliyor..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"SD kartın bağlantısı kesiliyor..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"USB dep brm silinyr..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"SD kart siliniyor..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"USB depolama birimi silinemedi."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"SD kart silinemedi."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD kart, bağlantısı kesilmeden çıkarıldı."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB depolama birimi şu anda denetleniyor."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SD kart şu anda denetleniyor."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD kart çıkarıldı."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB depolama birimi, şu anda bir bilgisayar tarafından kullanılıyor."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SD kart şu anda bir bilgisayar tarafından kullanılıyor."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Harici medyanın durumu bilinmiyor."</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 697eb98..00dc242 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"关机"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"正在关机..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"您的手机会关机。"</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"近期任务"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"没有最近的应用程序。"</string>
     <string name="global_actions" msgid="2406416831541615258">"手机选项"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"开发工具"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"只有应用程序开发人员才会用到的功能。"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"存储"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"访问 SD 卡。"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"访问 USB 存储设备。"</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"访问 SD 卡。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"停用或修改状态栏"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"允许应用程序停用状态栏或者增删系统图标。"</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"状态栏"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"允许应用程序通过删除应用程序缓存目录中的文件释放手机存储空间。通常此权限只适用于系统进程。"</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"移动应用程序资源"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"允许应用程序在内部介质和外部介质之间移动应用程序资源。"</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"查阅敏感日志数据"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"允许应用程序从系统的各个日志文件中读取信息。这样,应用程序就可以发现关于您手机使用情况的一般信息,其中可能包含个人信息或私密信息。"</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"读取/写入诊断所拥有的资源"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"允许应用程序读取/写入诊断组所拥有的任何资源(例如,/dev 中的文件)。这可能会影响系统稳定性和安全性。此权限仅供制造商或运营商诊断硬件问题。"</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"启用或停用应用程序组件"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"允许应用程序装载和卸载可移动存储器的文件系统。"</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"格式化外部存储设备"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"允许应用程序格式化可移除的存储设备。"</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"获取有关安全存储的信息"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"允许应用程序获取有关安全存储的信息。"</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"创建安全存储"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"允许应用程序创建安全存储。"</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"清除安全存储"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"允许应用程序清除安全存储。"</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"安装/卸载安全存储"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"允许应用程序安装/卸载安全存储。"</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"重命名安全存储"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"允许应用程序重命名安全存储。"</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"获取有关内部存储设备的信息"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"允许应用程序获取有关内部存储设备的信息。"</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"创建内部存储设备"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"允许应用程序创建内部存储设备。"</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"清除内部存储设备"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"允许应用程序清除内部存储设备。"</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"装载/卸载内部存储设备"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"允许应用程序装载/卸载内部存储设备。"</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"重命名内部存储设备"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"允许应用程序重命名内部存储设备。"</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"控制振动器"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"允许应用程序控制振动器。"</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"控制闪光灯"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"允许应用程序配置本地蓝牙手机,以及发现远程设备并与其配对。"</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"创建蓝牙连接"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"允许应用程序查看本地蓝牙手机的配置,以及建立或接受与配对设备的连接。"</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"控制近距离通信"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"允许应用程序与近距离通信 (NFC) 标签、卡和读卡器进行通信。"</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"停用键锁"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"允许应用程序停用键锁和任何关联的密码安全设置。例如,在手机上接听电话时停用键锁,在通话结束后重新启用键锁。"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"读取同步设置"</string>
@@ -420,22 +423,25 @@
     <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="permdesc_sdcardWrite" msgid="6643963204976471878">"允许应用程序写入 SD 卡。"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"修改/删除 USB 存储设备内容"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"修改/删除 SD 卡中的内容"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"允许应用程序写入 USB 存储设备。"</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"允许应用程序写入 SD 卡。"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"访问缓存文件系统"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"允许应用程序读取和写入缓存文件系统。"</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"限制密码选择"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"限制您能够使用的密码类型。"</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"监控登录尝试"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"监控对于登录设备和执行某项操作的失败尝试。"</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"重置密码"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"强行更新密码,您需要获得管理员提供的新密码才能登录。"</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"强行锁定"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"控制何时锁定设备,这需要您重新输入密码。"</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"拨打/接听互联网通话"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"允许应用程序使用 SIP 服务拨打/接听互联网通话。"</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"控制屏幕解锁密码允许的长度和字符数"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"监视锁定屏幕前密码输入错误的次数;如果密码输入错误次数太多,则会锁定手机或擦除手机上的所有数据。"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"更改屏幕解锁密码"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"更改屏幕解锁密码"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"锁定屏幕"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"控制锁定屏幕的方式和时间"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"清除所有数据"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"恢复出厂设置,这会在不提示确认的情况下删除您的所有数据。"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"恢复出厂设置时,将擦除手机上的数据而不发送警告"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"设置设备全局代理"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"请设置在启用政策的情况下要使用的设备全局代理。只有第一设备管理员才可设置有效的全局代理。"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"住宅"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"公司"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"其他"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"自定义"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"自定义"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"住宅"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"单位"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"其他"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"输入 PIN 码"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"输入密码进行解锁"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"输入 PIN 进行解锁"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"提示:点按两次可放大和缩小。"</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"自动填充此表单"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"读取浏览器的历史记录和书签"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允许应用程序读取用浏览器访问过的所有网址,以及浏览器的所有书签。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"写入浏览器的历史记录和书签"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"允许应用程序修改存储在手机中的浏览器历史记录或书签。恶意应用程序可借此清除或修改浏览器数据。"</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"在闹钟中设置警报"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"允许应用程序在安装的闹钟应用程序中设置警报。某些闹钟应用程序没有实现此功能。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"修改浏览器的地理位置权限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"允许应用程序修改浏览器的地理位置权限。恶意应用程序会利用这一点将位置信息发送到任意网站。"</string>
     <string name="save_password_message" msgid="767344687139195790">"是否希望浏览器记住此密码?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"强行关闭"</string>
     <string name="report" msgid="4060218260984795706">"报告"</string>
     <string name="wait" msgid="7147118217226317732">"等待"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"应用程序已重定向"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g>目前正在运行。"</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g>已启动。"</string>
     <string name="smv_application" msgid="295583804361236288">"应用程序<xliff:g id="APPLICATION">%1$s</xliff:g>(<xliff:g id="PROCESS">%2$s</xliff:g> 进程)违反了自我强制执行的严格模式 (StrictMode) 政策。"</string>
     <string name="smv_process" msgid="5120397012047462446">"进程 <xliff:g id="PROCESS">%1$s</xliff:g> 违反了自我强制执行的严格模式 (StrictMode) 政策。"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g>正在运行"</string>
@@ -800,25 +800,30 @@
     <string name="no_permissions" msgid="7283357728219338112">"不需要任何权限"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"隐藏"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"全部显示"</b></string>
-    <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB 大容量存储"</string>
+    <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB 大容量存储设备"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB 已连接"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"您已通过 USB 将手机连接至计算机。如果您要在计算机和 Android 手机的 SD 卡之间复制文件,请点击下面的按钮。"</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"您已通过 USB 将手机连接至计算机。如果您要在计算机与 Android 手机的 USB 存储设备之间复制文件,请点击下面的按钮。"</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"您已通过 USB 将手机连接至计算机。如果您要在计算机和 Android 手机的 SD 卡之间复制文件,请点击下面的按钮。"</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"打开 USB 存储设备"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"使用 SD 卡进行 USB 存储时出现问题。"</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"使用 USB 存储设备作为 USB 大容量存储设备时出现问题。"</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"使用 SD 卡作为 USB 大容量存储设备时出现问题。"</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 已连接"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"选择将文件复制到计算机或从计算机复制到存储设备。"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"关闭 USB 存储设备"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"选中以关闭 USB 存储设备。"</string>
-    <string name="usb_storage_stop_title" msgid="660129851708775853">"使用中的 USB 存储设备"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"在关闭 USB 存储设备前,请确保您已从计算机中卸载(“弹出”)Android 手机的 SD 卡。"</string>
+    <string name="usb_storage_stop_title" msgid="660129851708775853">"USB 存储设备正在使用中"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"在关闭 USB 存储设备前,请确保您已从计算机中卸载(“弹出”)Android 手机的 USB 存储设备。"</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"在关闭 USB 存储设备前,请确保您已从计算机中卸载(“弹出”)Android 手机的 SD 卡。"</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"关闭 USB 存储设备"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"关闭 USB 存储设备时遇到问题。请检查并确保已卸载了 USB 主设备,然后重试。"</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"打开 USB 存储设备"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"如果您打开了 USB 存储设备,则您当前使用的某些应用程序会停止,而且在您关闭 USB 存储设备前可能都无法使用。"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB 操作失败"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"确定"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"格式化 SD 卡"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"确定要将 SD 卡格式化吗?该卡上的所有数据都将丢失。"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 存储设备"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"格式化 SD 卡"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"确定要格式化 USB 存储设备,清除其中存储的全部文件吗?该操作将无法撤消!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"确定要将 SD 卡格式化吗?该卡上的所有数据都将丢失。"</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"格式化"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"已连接 USB 调试"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"选择停用 USB 调试。"</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"候选"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"正在准备 SD 卡"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"正在准备 USB 存储设备"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"正在准备 SD 卡"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"正在检查是否有错误。"</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"空 SD 卡"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"SD 卡无文件系统,或文件系统不受支持。"</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"SD 卡受损"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"SD 卡已损坏。您可能必须将其重新格式化。"</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"SD 卡未正常移除"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"请先卸载 SD 卡,再将其移除,以防数据丢失。"</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"SD 卡已安全移除"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"您现在可以安全移除 SD 卡。"</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"已移除 SD 卡"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"SD 卡已移除。请插入新的 SD 卡。"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"USB 存储设备中无文件"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"空 SD 卡"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB 存储设备中无文件或使用了不支持的文件系统。"</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD 卡无文件系统,或文件系统不受支持。"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB 存储设备已损坏"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"SD 卡受损"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB 存储设备已损坏,您可能需要对其重新格式化。"</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD 卡已损坏。您可能必须将其重新格式化。"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB 存储设备已意外移除"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD 卡未正常移除"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"请先卸载 USB 存储设备,再将其移除,以防数据丢失。"</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"请先卸载 SD 卡,再将其移除,以防数据丢失。"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB 存储设备已安全移除"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD 卡已安全移除"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"您可以安全地移除 USB 存储设备。"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"您现在可以安全移除 SD 卡。"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB 存储设备已移除"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"已移除 SD 卡"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB 存储设备已移除。请插入新媒体。"</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD 卡已移除。请插入新的 SD 卡。"</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"找不到匹配的活动"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"更新组件使用情况统计"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"允许修改收集的组件使用情况统计。普通应用程序不能使用此权限。"</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 个匹配项"</item>
     <item quantity="other" msgid="4641872797067609177">"第 <xliff:g id="INDEX">%d</xliff:g> 项,共 <xliff:g id="TOTAL">%d</xliff:g> 项"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"正在卸载 USB 存储设备..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"正在卸载 SD 卡..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"正在格式化 USB 存储设备"</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"正在格式化 SD 卡..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"USB 存储设备格式化失败。"</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"SD 卡格式化失败。"</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD 卡尚未卸载就被移除。"</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"系统正在检查 USB 存储设备。"</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"目前正在检查 SD 卡。"</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD 卡已移除。"</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"某台计算机正在使用 USB 存储设备。"</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"目前有计算机正在使用 SD 卡。"</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"外部媒体处于未知状态。"</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5dbd8a3..a6c77c9 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -135,6 +135,8 @@
     <string name="power_off" msgid="4266614107412865048">"關機"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"關機中..."</string>
     <string name="shutdown_confirm" msgid="649792175242821353">"手機即將關機。"</string>
+    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
+    <skip />
     <string name="recent_tasks_title" msgid="3691764623638127888">"最新的"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"最近沒有存取應用程式。"</string>
     <string name="global_actions" msgid="2406416831541615258">"電話選項"</string>
@@ -169,7 +171,8 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"開發工具"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"只有開發者需要此功能。"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"儲存"</string>
-    <string name="permgroupdesc_storage" msgid="9203302214915355774">"存取 SD 卡。"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"存取 USB 儲存裝置。"</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"存取 SD 卡。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"停用或變更狀態列"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"允許應用程式停用狀態列或新增、移除系統圖示。"</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"狀態列"</string>
@@ -266,10 +269,8 @@
     <string name="permdesc_clearAppCache" msgid="7740465694193671402">"允許應用程式刪除快取目錄裡的檔案,釋放儲存空間。此操作通常受到系統程序嚴格限制。"</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"移動應用程式資源"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"允許應用程式將應用程式資源從內部媒體移到外部媒體,反之亦可。"</string>
-    <!-- no translation found for permlab_readLogs (6615778543198967614) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (8896449437464867766) -->
-    <skip />
+    <string name="permlab_readLogs" msgid="6615778543198967614">"讀取機密記錄資料"</string>
+    <string name="permdesc_readLogs" msgid="8896449437464867766">"允許應用程式讀取系統的各種記錄檔。這會允許應用程式搜尋一般性的電話使用資訊,可能包含您的個人或私人資訊。"</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"讀寫 diag 擁有的資源"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"允許應用程式讀寫 diag 群組的資源;例如:/dev 裡的檔案。這可能會影響系統穩定性與安全性。此功能僅供製造商或技術人員用於硬體規格偵測。"</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"啟用或停用應用程式元件"</string>
@@ -322,16 +323,16 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"允許應用程式掛載/卸載抽取式儲存設備的檔案系統。"</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"將外接式儲存裝置格式化"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"允許應用程式將可移除式儲存裝置格式化。"</string>
-    <string name="permlab_asec_access" msgid="1070364079249834666">"取得安全儲存空間的資訊"</string>
-    <string name="permdesc_asec_access" msgid="7691616292170590244">"允許應用程式取得安全儲存空間的資訊。"</string>
-    <string name="permlab_asec_create" msgid="7312078032326928899">"建立安全儲存空間"</string>
-    <string name="permdesc_asec_create" msgid="7041802322759014035">"允許應用程式建立安全儲存空間。"</string>
-    <string name="permlab_asec_destroy" msgid="7787322878955261006">"銷毀安全儲存空間"</string>
-    <string name="permdesc_asec_destroy" msgid="5740754114967893169">"允許應用程式銷毀安全儲存空間。"</string>
-    <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"掛載/卸載安全儲存空間"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"允許應用程式掛載/卸載安全儲存空間。"</string>
-    <string name="permlab_asec_rename" msgid="5685344390439934495">"重新命名安全儲存空間"</string>
-    <string name="permdesc_asec_rename" msgid="1387881770708872470">"允許應用程式重新命名安全儲存空間。"</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"取得內存空間的資訊"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"允許應用程式取得內存空間的資訊。"</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"建立內存空間"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"允許應用程式建立內存空間。"</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"銷毀內存空間"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"允許應用程式銷毀內存空間。"</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"掛接/卸載內存空間"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"允許應用程式掛接/卸載內存空間。"</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"重新命名內存空間"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"允許應用程式重新命名內存空間。"</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"控制震動"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"允許應用程式控制震動。"</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"控制閃光燈"</string>
@@ -404,6 +405,8 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"允許應用程式設定本機藍牙電話,以及偵測與配對其他遠端裝置。"</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"建立藍牙連線"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"允許應用程式檢視本機藍牙電話設定,並與其他配對裝置連線。"</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"控制近距離無線通訊"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"允許應用程式使用近距離無線通訊 (NFC) 標記、卡片及讀取程式進行通訊。"</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"停用按鍵鎖定"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"允許應用程式停用按鍵鎖定以及其他相關的密碼安全性。例如:收到來電時解除按鍵鎖定,通話結束後重新啟動按鍵鎖定。"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"讀取同步處理設定"</string>
@@ -420,22 +423,25 @@
     <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="permdesc_sdcardWrite" msgid="6643963204976471878">"允許應用程式寫入 SD 卡。"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"修改/刪除 USB 儲存裝置內容"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"修改/刪除 SD 卡的內容"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"允許應用程式寫入 USB 儲存裝置。"</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"允許應用程式寫入 SD 卡。"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"存取快取檔案系統"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"允許應用程式讀取及寫入快取檔案系統。"</string>
-    <string name="policylab_limitPassword" msgid="4307861496302850201">"限制密碼設定規則"</string>
-    <string name="policydesc_limitPassword" msgid="1719877245692318299">"限制允許使用的密碼類型。"</string>
-    <string name="policylab_watchLogin" msgid="7374780712664285321">"查看登入嘗試記錄"</string>
-    <string name="policydesc_watchLogin" msgid="1961251179624843483">"監視者無法登入裝置執行部分動作。"</string>
-    <string name="policylab_resetPassword" msgid="9084772090797485420">"重設密碼"</string>
-    <string name="policydesc_resetPassword" msgid="3332167600331799991">"強制重新設定密碼。您必須取得以管理員提供的新密碼,才能登入。"</string>
-    <string name="policylab_forceLock" msgid="5760466025247634488">"強制鎖定"</string>
-    <string name="policydesc_forceLock" msgid="2819868664946089740">"裝置鎖定時可取得控制,但必須重新輸入密碼。"</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"撥打/接聽網路電話"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"允許應用程式使用 SIP 服務撥打/接聽網路電話。"</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"控制螢幕解鎖密碼所允許的長度和字元"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"監視螢幕解鎖時密碼輸入錯誤的次數,如果密碼輸入錯誤的次數過多,則會鎖定手機或清除手機的所有資料"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"變更螢幕解鎖密碼"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"變更螢幕解鎖密碼"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"鎖定螢幕"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"控制鎖定螢幕的方式和時間"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"清除所有資料"</string>
-    <string name="policydesc_wipeData" msgid="2314060933796396205">"重設為原廠設定 (系統會刪除所有資料,且不會向您進行確認)。"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"執行重設為原廠設定時,系統會直接清除手機資料而不提出警告"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"設定裝置全域 Proxy"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"設定政策啟用時所要使用的裝置全域 Proxy,只有第一個裝置管理員所設定的全域 Proxy 具有效力。"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"住家電話"</item>
@@ -530,14 +536,10 @@
     <string name="orgTypeWork" msgid="29268870505363872">"公司"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"其他"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"自訂"</string>
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"自訂"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"住家"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"公司"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"其他"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"輸入 PIN 碼"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"輸入密碼即可解鎖"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"輸入 PIN 進行解鎖"</string>
@@ -598,12 +600,13 @@
     <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>
     <string name="double_tap_toast" msgid="1068216937244567247">"提示:輕按兩下可放大縮小。"</string>
-    <!-- no translation found for autofill_this_form (8940110866775097494) -->
-    <skip />
+    <string name="autofill_this_form" msgid="8940110866775097494">"自動填寫此表單"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"讀取瀏覽器的記錄與書籤"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允許應用程式讀取瀏覽器曾經造訪過的所有網址,以及瀏覽器的所有書籤。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"寫入瀏覽器的記錄與書籤"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"允許應用程式修改儲存在電話上的瀏覽記錄或書籤。請注意:惡意應用程式可能會使用此選項來清除或修改您瀏覽器的資料。"</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"在鬧鐘應用程式中設定鬧鈴"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"允許應用程式設定您所安裝的鬧鐘應用程式執行鬧鈴功能 (有些鬧鐘應用程式並不支援此功能)。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"修改瀏覽器地理資訊的權限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"允許應用程式修改瀏覽器的地理位置權限,惡意應用程式可能會透過此方式允許將您的位置資訊任意傳送給某些網站。"</string>
     <string name="save_password_message" msgid="767344687139195790">"是否記住此密碼?"</string>
@@ -750,12 +753,9 @@
     <string name="force_close" msgid="3653416315450806396">"強制關閉"</string>
     <string name="report" msgid="4060218260984795706">"回報"</string>
     <string name="wait" msgid="7147118217226317732">"等待"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"應用程式已重新導向"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」現在正在執行。"</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」原先已啟動。"</string>
     <string name="smv_application" msgid="295583804361236288">"應用程式 <xliff:g id="APPLICATION">%1$s</xliff:g> (處理程序 <xliff:g id="PROCESS">%2$s</xliff:g>) 已違反其自行強制實施的嚴格模式 (StrictMode) 政策。"</string>
     <string name="smv_process" msgid="5120397012047462446">"處理程序 <xliff:g id="PROCESS">%1$s</xliff:g> 已違反其自行強制實施的嚴格模式 (StrictMode) 政策。"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> 執行中"</string>
@@ -802,23 +802,28 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"顯示全部"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB 大量儲存裝置"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB 已連接"</string>
-    <string name="usb_storage_message" msgid="4796759646167247178">"已透過 USB 連接手機與電腦。如要從電腦或 Android 系統的 SD 卡複製檔案,請選取下方按鈕。"</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="115779324551502062">"已透過 USB 連接手機與電腦。如要在電腦和 Android 的 USB 儲存裝置之間複製檔案,請選取下方按鈕。"</string>
+    <string name="usb_storage_message" product="default" msgid="4796759646167247178">"已透過 USB 連接手機與電腦。如要從電腦或 Android 系統的 SD 卡複製檔案,請選取下方按鈕。"</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"開啟 USB 儲存裝置"</string>
-    <string name="usb_storage_error_message" msgid="2534784751603345363">"把 SD 卡當成 USB 儲存裝置時發生問題。"</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"使用您的 USB 儲存裝置作為 USB 大量儲存裝置時發生問題。"</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"使用您的 SD 卡作為 USB 大量儲存裝置時發生問題。"</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 已連接"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"選取此項將檔案複製到電腦,或從電腦複製。"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"關閉 USB 儲存裝置"</string>
-    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"選取此處關閉 USB 儲存裝置。"</string>
+    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"選取此處可關閉 USB 儲存裝置。"</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB 儲存空間使用中"</string>
-    <string name="usb_storage_stop_message" msgid="3613713396426604104">"關閉 USB 儲存裝置前,請務必先將 Android 系統的 SD 卡從電腦上卸下 (退出)。"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"關閉 USB 儲存裝置前,請務必先從電腦卸載 (退出) Android 手機的 USB 儲存裝置。"</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"關閉 USB 儲存裝置前,請務必先將 Android 系統的 SD 卡從電腦上卸下 (退出)。"</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"關閉 USB 儲存裝置"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"關閉 USB 儲存裝置時發生問題。請檢查您是否已卸載 USB Host,然後再試一次。"</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"開啟 USB 儲存裝置"</string>
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"如果您開啟 USB 儲存裝置,則您正在使用的某些應用程式會停止運作,而且可能無法使用,待您將 USB 儲存裝置關閉才會恢復正常。"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB 操作失敗"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"確定"</string>
-    <string name="extmedia_format_title" msgid="8663247929551095854">"將 SD 卡格式化"</string>
-    <string name="extmedia_format_message" msgid="3621369962433523619">"確定要將 SD 卡格式化嗎?該 SD 卡中的所有資料將會遺失。"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 儲存空間"</string>
+    <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"將 SD 卡格式化"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"格式化 USB 儲存裝置時,是否清除其中儲存的所有檔案?這項動作無法復原!"</string>
+    <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"確定要將 SD 卡格式化嗎?該 SD 卡中的所有資料將會遺失。"</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"格式化"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB 偵錯模式已啟用"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"選取以停用 USB 偵錯。"</string>
@@ -826,18 +831,29 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"待選項目"</u></string>
-    <string name="ext_media_checking_notification_title" msgid="5457603418970994050">"正在準備 SD 卡"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"正在準備 USB 儲存裝置"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"正在準備 SD 卡"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"正在檢查錯誤。"</string>
-    <string name="ext_media_nofs_notification_title" msgid="780477838241212997">"SD 卡為空白"</string>
-    <string name="ext_media_nofs_notification_message" msgid="3817704088027829380">"SD 卡內無檔案系統,或檔案系統不受支援。"</string>
-    <string name="ext_media_unmountable_notification_title" msgid="6410723906019100189">"SD 卡已損壞"</string>
-    <string name="ext_media_unmountable_notification_message" msgid="6902531775948238989">"SD 卡已毀損,您可能必須予以重新格式化。"</string>
-    <string name="ext_media_badremoval_notification_title" msgid="6872152882604407837">"SD 卡未正常移除"</string>
-    <string name="ext_media_badremoval_notification_message" msgid="7260183293747448241">"請先卸載 SD 卡,再將其移除,以免資料遺失。"</string>
-    <string name="ext_media_safe_unmount_notification_title" msgid="6729801130790616200">"可安全移除 SD 卡"</string>
-    <string name="ext_media_safe_unmount_notification_message" msgid="568841278138377604">"您現在可以安全地移除 SD 卡。"</string>
-    <string name="ext_media_nomedia_notification_title" msgid="8902518030404381318">"已移除 SD 卡"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="3870120652983659641">"SD 卡已移除,請插入新的 SD 卡。"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"USB 儲存裝置無內容"</string>
+    <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"SD 卡為空白"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB 儲存裝置無內容或使用不受支援的檔案系統。"</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD 卡內無檔案系統,或檔案系統不受支援。"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB 儲存裝置已毀損"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"SD 卡已損壞"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB 儲存裝置已損壞,您可能必須重新格式化。"</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD 卡已毀損,您可能必須予以重新格式化。"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB 儲存裝置已意外移除"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD 卡未正常移除"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"請先卸載 USB 儲存裝置,再將其移除,以免資料遺失。"</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"請先卸載 SD 卡,再將其移除,以免資料遺失。"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB 儲存裝置已可安全移除"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"可安全移除 SD 卡"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"您可安全移除 USB 儲存裝置了。"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"您現在可以安全地移除 SD 卡。"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB 儲存裝置已移除"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"已移除 SD 卡"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB 儲存裝置已移除,請插入新媒體。"</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD 卡已移除,請插入新的 SD 卡。"</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"找不到符合的活動"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"更新元件使用統計資料"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"允許修改收集到的元件使用統計資料。一般應用程式不會使用此功能。"</string>
@@ -892,4 +908,23 @@
     <item quantity="one" msgid="8167147081136579439">"1 個相符項目"</item>
     <item quantity="other" msgid="4641872797067609177">"第 <xliff:g id="INDEX">%d</xliff:g> 個相符項目 (共 <xliff:g id="TOTAL">%d</xliff:g> 個相符項目)"</item>
   </plurals>
+    <!-- no translation found for action_mode_done (7217581640461922289) -->
+    <skip />
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"正在卸載 USB 儲存裝置..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"正在卸載 SD 卡..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"正在清除 USB 儲存裝置..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"正在清除 SD 卡..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"無法清除 USB 儲存裝置。"</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"無法清除 SD 卡。"</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD 卡尚未卸載就已移除。"</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB 儲存裝置目前正在接受檢查。"</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SD 卡目前正在接受檢查。"</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD 卡已移除。"</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"電腦目前正在使用 USB 儲存裝置。"</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"電腦目前正在使用 SD 卡。"</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"外部媒體狀態不明。"</string>
+    <!-- no translation found for share (1778686618230011964) -->
+    <skip />
+    <!-- no translation found for find (4808270900322985960) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c8eb7fd..a6953d4 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -290,6 +290,11 @@
 
     <bool name="config_use_strict_phone_number_comparation">false</bool>
 
+    <!-- Display low battery warning when battery level dips to this value.
+         Also, the battery stats are flushed to disk when we hit this level.  -->
+    <integer name="config_criticalBatteryWarningLevel">4</integer>
+
+    <!-- Display low battery warning when battery level dips to this value -->
     <!-- Display low battery warning when battery level dips to this value -->
     <integer name="config_lowBatteryWarningLevel">15</integer>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 749b3c7..8b9bc43 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1440,6 +1440,37 @@
     <!-- Custom organization type -->
     <string name="orgTypeCustom">Custom</string>
 
+    <!-- Custom relationship custom [CHAR LIMIT=20] -->
+    <string name="relationTypeCustom">Custom</string>
+    <!-- Assistant relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeAssistant">Assistant</string>
+    <!-- Brother relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeBrother">Brother</string>
+    <!-- Child relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeChild">Child</string>
+    <!-- Domestic Partner relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeDomesticPartner">Domestic Partner</string>
+    <!-- Father relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeFather">Father</string>
+    <!-- Friend relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeFriend">Friend</string>
+    <!-- Manager relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeManager">Manager</string>
+    <!-- Mother relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeMother">Mother</string>
+    <!-- Parent relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeParent">Parent</string>
+    <!-- Partner relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypePartner">Partner</string>
+    <!-- Referred by relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeReferredBy">Referred by</string>
+    <!-- Relative relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeRelative">Relative</string>
+    <!-- Sister relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeSister">Sister</string>
+    <!-- Spouse relationship type [CHAR LIMIT=20] -->
+    <string name="relationTypeSpouse">Spouse</string>
+    
     <!-- Custom SIP address type -->
     <string name="sipAddressTypeCustom">Custom</string>
     <!-- Home SIP address type -->
@@ -1652,7 +1683,21 @@
     <string name="double_tap_toast">Tip: double-tap to zoom in and out.</string>
 
     <!-- Text to show in the auto complete drop down list on a text view when the browser can auto fill the entire form -->
-    <string name="autofill_this_form">AutoFill this form</string>
+    <string name="autofill_this_form">AutoFill</string>
+
+    <!-- String used to separate FirstName and LastName when writing out a local name
+         e.g. John<separator>Smith [CHAR-LIMIT=NONE]-->
+    <string name="autofill_address_name_separator">\u0020</string>
+    <!-- Format string for displaying a name. $1 is First Name, $2 is autofill_address_name_separator, $3 is Last Name.
+         e.g. (John)( )(Smith) -->
+    <string name="autofill_address_summary_name_format">$1$2$3</string>
+
+    <!-- String used to separate Name and Address Line 1
+         e.g. John Smith<separator>123 Main Street [CHAR-LIMIT=NONE]-->
+    <string name="autofill_address_summary_separator">,\u0020</string>
+    <!-- Format string for displaying a name and address summary. $1 is the Full Name, $2 is autofill_address_summary_separator, $3 is the Address
+         e.g. (John Smith)(, )(123 Main Street) -->
+    <string name="autofill_address_summary_format">$1$2$3</string>
 
     <!-- Title of an application permission, listed so the user can choose whether
         they want to allow the application to do this. -->
@@ -2379,11 +2424,6 @@
         <item quantity="other"><xliff:g id="index" example="2">%d</xliff:g> of <xliff:g id="total" example="137">%d</xliff:g></item>
     </plurals>
 
-    <!-- Warning message about security implications of enabling an input method, displayed as a dialog message when the user selects to enable an IME. -->
-    <string name="ime_enabler_security_warning">This input method may be able to collect all the text you type, including personal data like passwords and credit card numbers. It comes from the application <xliff:g id="ime_application_name">%1$s</xliff:g>. Use this input method?</string>
-    <!-- Label for selecting the input method to use -->
-    <string name="ime_enabler_subtype_title">Select inputmethods in <xliff:g id="ime_application_name">%1$s</xliff:g></string>
-
     <!-- Label for the "Done" button on the far left of action mode toolbars. -->
     <string name="action_mode_done">Done</string>
 
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 76a3c34..61167b5 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -408,7 +408,7 @@
     <style name="Widget.TextView.ListSeparator">
         <item name="android:background">@android:drawable/dark_header_dither</item>
         <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">25dip</item>
+        <item name="android:layout_height">wrap_content</item>
         <item name="android:textStyle">bold</item>
         <item name="android:textColor">?textColorSecondary</item>
         <item name="android:textSize">14sp</item>
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
index d8d9eba..f019599 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
@@ -42,6 +42,10 @@
 
     public void testEnable() {
         int iterations = BluetoothTestRunner.sEnableIterations;
+        if (iterations == 0) {
+            return;
+        }
+
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
 
         for (int i = 0; i < iterations; i++) {
@@ -53,6 +57,10 @@
 
     public void testDiscoverable() {
         int iterations = BluetoothTestRunner.sDiscoverableIterations;
+        if (iterations == 0) {
+            return;
+        }
+
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         mTestUtils.enable(adapter);
 
@@ -67,6 +75,10 @@
 
     public void testScan() {
         int iterations = BluetoothTestRunner.sScanIterations;
+        if (iterations == 0) {
+            return;
+        }
+
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         mTestUtils.enable(adapter);
 
@@ -78,4 +90,67 @@
 
         mTestUtils.disable(adapter);
     }
+
+    public void testPair() {
+        int iterations = BluetoothTestRunner.sPairIterations;
+        if (iterations == 0) {
+            return;
+        }
+
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sPairAddress);
+        mTestUtils.enable(adapter);
+
+        for (int i = 0; i < iterations; i++) {
+            mTestUtils.writeOutput("pair iteration " + (i + 1) + " of " + iterations);
+            mTestUtils.pair(adapter, device, BluetoothTestRunner.sPairPasskey,
+                    BluetoothTestRunner.sPairPin);
+            mTestUtils.unpair(adapter, device);
+        }
+        mTestUtils.disable(adapter);
+    }
+
+    public void testConnectA2dp() {
+        int iterations = BluetoothTestRunner.sConnectA2dpIterations;
+        if (iterations == 0) {
+            return;
+        }
+
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sA2dpAddress);
+        mTestUtils.enable(adapter);
+        mTestUtils.pair(adapter, device, BluetoothTestRunner.sPairPasskey,
+                BluetoothTestRunner.sPairPin);
+
+        for (int i = 0; i < iterations; i++) {
+            mTestUtils.writeOutput("connectA2dp iteration " + (i + 1) + " of " + iterations);
+            mTestUtils.connectProfile(adapter, device, BluetoothProfile.A2DP);
+            mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.A2DP);
+        }
+
+        // TODO: Unpair from device if device can accept pairing after unpairing
+        mTestUtils.disable(adapter);
+    }
+
+    public void testConnectHeadset() {
+        int iterations = BluetoothTestRunner.sConnectHeadsetIterations;
+        if (iterations == 0) {
+            return;
+        }
+
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sHeadsetAddress);
+        mTestUtils.enable(adapter);
+        mTestUtils.pair(adapter, device, BluetoothTestRunner.sPairPasskey,
+                BluetoothTestRunner.sPairPin);
+
+        for (int i = 0; i < iterations; i++) {
+            mTestUtils.writeOutput("connectHeadset iteration " + (i + 1) + " of " + iterations);
+            mTestUtils.connectProfile(adapter, device, BluetoothProfile.HEADSET);
+            mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.HEADSET);
+        }
+
+        // TODO: Unpair from device if device can accept pairing after unpairing
+        mTestUtils.disable(adapter);
+    }
 }
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
index cf0ff99..3e589fc 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
@@ -21,11 +21,24 @@
 import android.os.Bundle;
 import android.test.InstrumentationTestRunner;
 import android.test.InstrumentationTestSuite;
+import android.util.Log;
 
 public class BluetoothTestRunner extends InstrumentationTestRunner {
+    private static final String TAG = "BluetoothTestRunner";
+
     public static int sEnableIterations = 100;
     public static int sDiscoverableIterations = 1000;
     public static int sScanIterations = 1000;
+    public static int sPairIterations = 100;
+    public static int sConnectHeadsetIterations = 100;
+    public static int sConnectA2dpIterations = 100;
+
+    public static String sPairAddress = "";
+    public static String sHeadsetAddress = "";
+    public static String sA2dpAddress = "";
+
+    public static byte[] sPairPin = {'1', '2', '3', '4'};
+    public static int sPairPasskey = 123456;
 
     @Override
     public TestSuite getAllTests() {
@@ -41,8 +54,6 @@
 
     @Override
     public void onCreate(Bundle arguments) {
-        super.onCreate(arguments);
-
         String val = arguments.getString("enable_iterations");
         if (val != null) {
             try {
@@ -69,5 +80,76 @@
                 // Invalid argument, fall back to default value
             }
         }
+
+        val = arguments.getString("pair_iterations");
+        if (val != null) {
+            try {
+                sPairIterations = Integer.parseInt(val);
+            } catch (NumberFormatException e) {
+                // Invalid argument, fall back to default value
+            }
+        }
+
+        val = arguments.getString("connect_a2dp_iterations");
+        if (val != null) {
+            try {
+                sConnectA2dpIterations = Integer.parseInt(val);
+            } catch (NumberFormatException e) {
+                // Invalid argument, fall back to default value
+            }
+        }
+
+        val = arguments.getString("connect_headset_iterations");
+        if (val != null) {
+            try {
+                sConnectHeadsetIterations = Integer.parseInt(val);
+            } catch (NumberFormatException e) {
+                // Invalid argument, fall back to default value
+            }
+        }
+
+        val = arguments.getString("pair_address");
+        if (val != null) {
+            sPairAddress = val;
+        }
+
+        val = arguments.getString("headset_address");
+        if (val != null) {
+            sHeadsetAddress = val;
+        }
+
+        val = arguments.getString("a2dp_address");
+        if (val != null) {
+            sA2dpAddress = val;
+        }
+
+        val = arguments.getString("pair_pin");
+        if (val != null) {
+            sPairPin = BluetoothDevice.convertPinToBytes(val);
+        }
+
+        val = arguments.getString("pair_passkey");
+        if (val != null) {
+            try {
+                sPairPasskey = Integer.parseInt(val);
+            } catch (NumberFormatException e) {
+                // Invalid argument, fall back to default value
+            }
+        }
+
+        Log.i(TAG, String.format("enable_iterations=%d", sEnableIterations));
+        Log.i(TAG, String.format("discoverable_iterations=%d", sDiscoverableIterations));
+        Log.i(TAG, String.format("scan_iterations=%d", sScanIterations));
+        Log.i(TAG, String.format("pair_iterations=%d", sPairIterations));
+        Log.i(TAG, String.format("connect_a2dp_iterations=%d", sConnectA2dpIterations));
+        Log.i(TAG, String.format("connect_headset_iterations=%d", sConnectHeadsetIterations));
+        Log.i(TAG, String.format("pair_address=%s", sPairAddress));
+        Log.i(TAG, String.format("a2dp_address=%s", sA2dpAddress));
+        Log.i(TAG, String.format("headset_address=%s", sHeadsetAddress));
+        Log.i(TAG, String.format("pair_pin=%s", new String(sPairPin)));
+        Log.i(TAG, String.format("pair_passkey=%d", sPairPasskey));
+
+        // Call onCreate last since we want to set the static variables first.
+        super.onCreate(arguments);
     }
 }
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index cddf63d..328891c 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -29,6 +29,8 @@
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 public class BluetoothTestUtils extends Assert {
 
@@ -57,73 +59,43 @@
      */
     private static final int CANCEL_DISCOVERY_TIMEOUT = 5000;
 
-    private static final int DISCOVERY_STARTED_FLAG = 1;
-    private static final int DISCOVERY_FINISHED_FLAG = 1 << 1;
-    private static final int SCAN_MODE_NONE_FLAG = 1 << 2;
-    private static final int SCAN_MODE_CONNECTABLE_FLAG = 1 << 3;
-    private static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG = 1 << 4;
-    private static final int STATE_OFF_FLAG = 1 << 5;
-    private static final int STATE_TURNING_ON_FLAG = 1 << 6;
-    private static final int STATE_ON_FLAG = 1 << 7;
-    private static final int STATE_TURNING_OFF_FLAG = 1 << 8;
+    /**
+     * Timeout for {@link BluetoothDevice#createBond()} in ms.
+     */
+    private static final int PAIR_TIMEOUT = 20000;
+
+    /**
+     * Timeout for {@link BluetoothDevice#removeBond()} in ms.
+     */
+    private static final int UNPAIR_TIMEOUT = 20000;
+
+    /**
+     * Timeout for {@link BluetoothProfile#connect(BluetoothDevice)} in ms.
+     */
+    private static final int CONNECT_PROFILE_TIMEOUT = 20000;
+
+    /**
+     * Timeout for {@link BluetoothProfile#disconnect(BluetoothDevice)} in ms.
+     */
+    private static final int DISCONNECT_PROFILE_TIMEOUT = 20000;
+
+    /**
+     * Timeout to connect a profile proxy in ms.
+     */
+    private static final int CONNECT_PROXY_TIMEOUT = 5000;
 
     /**
      * Time between polls in ms.
      */
     private static final int POLL_TIME = 100;
 
-    private Context mContext;
-
-    private BufferedWriter mOutputWriter;
-
-    private String mOutputFile;
-    private String mTag;
-
-    private class BluetoothReceiver extends BroadcastReceiver {
+    private abstract class FlagReceiver extends BroadcastReceiver {
+        private int mExpectedFlags = 0;
         private int mFiredFlags = 0;
+        private long mCompletedTime = -1;
 
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            synchronized (this) {
-                if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
-                    mFiredFlags |= DISCOVERY_STARTED_FLAG;
-                } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
-                    mFiredFlags |= DISCOVERY_FINISHED_FLAG;
-                } else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) {
-                    int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,
-                            BluetoothAdapter.ERROR);
-                    assertNotSame(mode, BluetoothAdapter.ERROR);
-                    switch (mode) {
-                        case BluetoothAdapter.SCAN_MODE_NONE:
-                            mFiredFlags |= SCAN_MODE_NONE_FLAG;
-                            break;
-                        case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
-                            mFiredFlags |= SCAN_MODE_CONNECTABLE_FLAG;
-                            break;
-                        case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
-                            mFiredFlags |= SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG;
-                            break;
-                    }
-                } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
-                    int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
-                            BluetoothAdapter.ERROR);
-                    assertNotSame(state, BluetoothAdapter.ERROR);
-                    switch (state) {
-                        case BluetoothAdapter.STATE_OFF:
-                            mFiredFlags |= STATE_OFF_FLAG;
-                            break;
-                        case BluetoothAdapter.STATE_TURNING_ON:
-                            mFiredFlags |= STATE_TURNING_ON_FLAG;
-                            break;
-                        case BluetoothAdapter.STATE_ON:
-                            mFiredFlags |= STATE_ON_FLAG;
-                            break;
-                        case BluetoothAdapter.STATE_TURNING_OFF:
-                            mFiredFlags |= STATE_TURNING_OFF_FLAG;
-                            break;
-                    }
-                }
-            }
+        public FlagReceiver(int expectedFlags) {
+            mExpectedFlags = expectedFlags;
         }
 
         public int getFiredFlags() {
@@ -132,14 +104,232 @@
             }
         }
 
-        public void resetFiredFlags() {
+        public long getCompletedTime() {
             synchronized (this) {
-                mFiredFlags = 0;
+                return mCompletedTime;
+            }
+        }
+
+        protected void setFiredFlag(int flag) {
+            synchronized (this) {
+                mFiredFlags |= flag;
+                if (mFiredFlags == mExpectedFlags) {
+                    mCompletedTime = System.currentTimeMillis();
+                }
             }
         }
     }
 
-    private BluetoothReceiver mReceiver = new BluetoothReceiver();
+    private class BluetoothReceiver extends FlagReceiver {
+        private static final int DISCOVERY_STARTED_FLAG = 1;
+        private static final int DISCOVERY_FINISHED_FLAG = 1 << 1;
+        private static final int SCAN_MODE_NONE_FLAG = 1 << 2;
+        private static final int SCAN_MODE_CONNECTABLE_FLAG = 1 << 3;
+        private static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG = 1 << 4;
+        private static final int STATE_OFF_FLAG = 1 << 5;
+        private static final int STATE_TURNING_ON_FLAG = 1 << 6;
+        private static final int STATE_ON_FLAG = 1 << 7;
+        private static final int STATE_TURNING_OFF_FLAG = 1 << 8;
+
+        public BluetoothReceiver(int expectedFlags) {
+            super(expectedFlags);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.i("BT", intent.toString());
+            if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
+                setFiredFlag(DISCOVERY_STARTED_FLAG);
+            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
+                setFiredFlag(DISCOVERY_FINISHED_FLAG);
+            } else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) {
+                int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, -1);
+                assertNotSame(-1, mode);
+                switch (mode) {
+                    case BluetoothAdapter.SCAN_MODE_NONE:
+                        setFiredFlag(SCAN_MODE_NONE_FLAG);
+                        break;
+                    case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
+                        setFiredFlag(SCAN_MODE_CONNECTABLE_FLAG);
+                        break;
+                    case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
+                        setFiredFlag(SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG);
+                        break;
+                }
+            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
+                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
+                assertNotSame(-1, state);
+                switch (state) {
+                    case BluetoothAdapter.STATE_OFF:
+                        setFiredFlag(STATE_OFF_FLAG);
+                        break;
+                    case BluetoothAdapter.STATE_TURNING_ON:
+                        setFiredFlag(STATE_TURNING_ON_FLAG);
+                        break;
+                    case BluetoothAdapter.STATE_ON:
+                        setFiredFlag(STATE_ON_FLAG);
+                        break;
+                    case BluetoothAdapter.STATE_TURNING_OFF:
+                        setFiredFlag(STATE_TURNING_OFF_FLAG);
+                        break;
+                }
+            }
+        }
+    }
+
+    private class PairReceiver extends FlagReceiver {
+        private static final int STATE_BONDED_FLAG = 1;
+        private static final int STATE_BONDING_FLAG = 1 << 1;
+        private static final int STATE_NONE_FLAG = 1 << 2;
+
+        private BluetoothDevice mDevice;
+        private int mPasskey;
+        private byte[] mPin;
+
+        public PairReceiver(BluetoothDevice device, int passkey, byte[] pin, int expectedFlags) {
+            super(expectedFlags);
+
+            mDevice = device;
+            mPasskey = passkey;
+            mPin = pin;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
+                return;
+            }
+
+            if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
+                int varient = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, -1);
+                assertNotSame(-1, varient);
+                switch(varient) {
+                    case BluetoothDevice.PAIRING_VARIANT_PIN:
+                        mDevice.setPin(mPin);
+                        break;
+                    case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
+                        mDevice.setPasskey(mPasskey);
+                        break;
+                    case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
+                    case BluetoothDevice.PAIRING_VARIANT_CONSENT:
+                        mDevice.setPairingConfirmation(true);
+                        break;
+                    case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
+                        mDevice.setRemoteOutOfBandData();
+                        break;
+                }
+            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
+                int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
+                assertNotSame(-1, state);
+                switch (state) {
+                    case BluetoothDevice.BOND_NONE:
+                        setFiredFlag(STATE_NONE_FLAG);
+                        break;
+                    case BluetoothDevice.BOND_BONDING:
+                        setFiredFlag(STATE_BONDING_FLAG);
+                        break;
+                    case BluetoothDevice.BOND_BONDED:
+                        setFiredFlag(STATE_BONDED_FLAG);
+                        break;
+                }
+            }
+        }
+    }
+
+    private class ConnectProfileReceiver extends FlagReceiver {
+        private static final int STATE_DISCONNECTED_FLAG = 1;
+        private static final int STATE_CONNECTING_FLAG = 1 << 1;
+        private static final int STATE_CONNECTED_FLAG = 1 << 2;
+        private static final int STATE_DISCONNECTING_FLAG = 1 << 3;
+
+        private BluetoothDevice mDevice;
+        private int mProfile;
+        private String mConnectionAction;
+
+        public ConnectProfileReceiver(BluetoothDevice device, int profile, int expectedFlags) {
+            super(expectedFlags);
+
+            mDevice = device;
+            mProfile = profile;
+
+            switch(mProfile) {
+                case BluetoothProfile.A2DP:
+                    mConnectionAction = BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED;
+                    break;
+                case BluetoothProfile.HEADSET:
+                    mConnectionAction = BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED;
+                    break;
+                default:
+                    mConnectionAction = null;
+            }
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+
+            if (mConnectionAction != null && mConnectionAction.equals(intent.getAction())) {
+                if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
+                    return;
+                }
+
+                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
+                assertNotSame(-1, state);
+                switch (state) {
+                    case BluetoothProfile.STATE_DISCONNECTED:
+                        setFiredFlag(STATE_DISCONNECTED_FLAG);
+                        break;
+                    case BluetoothProfile.STATE_CONNECTING:
+                        setFiredFlag(STATE_CONNECTING_FLAG);
+                        break;
+                    case BluetoothProfile.STATE_CONNECTED:
+                        setFiredFlag(STATE_CONNECTED_FLAG);
+                        break;
+                    case BluetoothProfile.STATE_DISCONNECTING:
+                        setFiredFlag(STATE_DISCONNECTING_FLAG);
+                        break;
+                }
+            }
+        }
+    }
+
+    private BluetoothProfile.ServiceListener mServiceListener =
+            new BluetoothProfile.ServiceListener() {
+        public void onServiceConnected(int profile, BluetoothProfile proxy) {
+            synchronized (this) {
+                switch (profile) {
+                    case BluetoothProfile.A2DP:
+                        mA2dp = (BluetoothA2dp) proxy;
+                        break;
+                    case BluetoothProfile.HEADSET:
+                        mHeadset = (BluetoothHeadset) proxy;
+                        break;
+                }
+            }
+        }
+
+        public void onServiceDisconnected(int profile) {
+            synchronized (this) {
+                switch (profile) {
+                    case BluetoothProfile.A2DP:
+                        mA2dp = null;
+                        break;
+                    case BluetoothProfile.HEADSET:
+                        mHeadset = null;
+                        break;
+                }
+            }
+        }
+    };
+
+    private List<BroadcastReceiver> mReceivers = new ArrayList<BroadcastReceiver>();
+
+    private BufferedWriter mOutputWriter;
+    private String mTag;
+    private String mOutputFile;
+
+    private Context mContext;
+    private BluetoothA2dp mA2dp;
+    private BluetoothHeadset mHeadset;
 
     public BluetoothTestUtils(Context context, String tag) {
         this(context, tag, null);
@@ -161,17 +351,12 @@
                 mOutputWriter = null;
             }
         }
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
-        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
-        filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
-        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
-        mContext.registerReceiver(mReceiver, filter);
     }
 
     public void close() {
-        mContext.unregisterReceiver(mReceiver);
+        while (!mReceivers.isEmpty()) {
+            mContext.unregisterReceiver(mReceivers.remove(0));
+        }
 
         if (mOutputWriter != null) {
             try {
@@ -183,25 +368,30 @@
     }
 
     public void enable(BluetoothAdapter adapter) {
-        int mask = STATE_TURNING_ON_FLAG | STATE_ON_FLAG | SCAN_MODE_CONNECTABLE_FLAG;
-        mReceiver.resetFiredFlags();
+        int mask = (BluetoothReceiver.STATE_TURNING_ON_FLAG | BluetoothReceiver.STATE_ON_FLAG
+                | BluetoothReceiver.SCAN_MODE_CONNECTABLE_FLAG);
+        long start = -1;
+        BluetoothReceiver receiver = getBluetoothReceiver(mask);
 
         int state = adapter.getState();
         switch (state) {
             case BluetoothAdapter.STATE_ON:
                 assertTrue(adapter.isEnabled());
+                removeReceiver(receiver);
                 return;
-            case BluetoothAdapter.STATE_OFF:
-            case BluetoothAdapter.STATE_TURNING_OFF:
-                assertFalse(adapter.isEnabled());
-                assertTrue(adapter.enable());
-                break;
             case BluetoothAdapter.STATE_TURNING_ON:
                 assertFalse(adapter.isEnabled());
                 mask = 0; // Don't check for received intents since we might have missed them.
                 break;
+            case BluetoothAdapter.STATE_OFF:
+            case BluetoothAdapter.STATE_TURNING_OFF:
+                assertFalse(adapter.isEnabled());
+                start = System.currentTimeMillis();
+                assertTrue(adapter.enable());
+                break;
             default:
-                fail("enable() invalid state: state=" + state);
+                removeReceiver(receiver);
+                fail(String.format("enable() invalid state: state=%d", state));
         }
 
         long s = System.currentTimeMillis();
@@ -209,10 +399,14 @@
             state = adapter.getState();
             if (state == BluetoothAdapter.STATE_ON) {
                 assertTrue(adapter.isEnabled());
-                if ((mReceiver.getFiredFlags() & mask) == mask) {
-                    mReceiver.resetFiredFlags();
-                    writeOutput(String.format("enable() completed in %d ms",
-                            (System.currentTimeMillis() - s)));
+                if ((receiver.getFiredFlags() & mask) == mask) {
+                    long finish = receiver.getCompletedTime();
+                    if (start != -1 && finish != -1) {
+                        writeOutput(String.format("enable() completed in %d ms", (finish - start)));
+                    } else {
+                        writeOutput("enable() completed");
+                    }
+                    removeReceiver(receiver);
                     return;
                 }
             } else {
@@ -222,27 +416,32 @@
             sleep(POLL_TIME);
         }
 
-        int firedFlags = mReceiver.getFiredFlags();
-        mReceiver.resetFiredFlags();
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
         fail(String.format("enable() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
                 state, BluetoothAdapter.STATE_ON, firedFlags, mask));
     }
 
     public void disable(BluetoothAdapter adapter) {
-        int mask = STATE_TURNING_OFF_FLAG | STATE_OFF_FLAG | SCAN_MODE_NONE_FLAG;
-        mReceiver.resetFiredFlags();
+        int mask = (BluetoothReceiver.STATE_TURNING_OFF_FLAG | BluetoothReceiver.STATE_OFF_FLAG
+                | BluetoothReceiver.SCAN_MODE_NONE_FLAG);
+        long start = -1;
+        BluetoothReceiver receiver = getBluetoothReceiver(mask);
 
         int state = adapter.getState();
         switch (state) {
             case BluetoothAdapter.STATE_OFF:
                 assertFalse(adapter.isEnabled());
+                removeReceiver(receiver);
                 return;
-            case BluetoothAdapter.STATE_ON:
-                assertTrue(adapter.isEnabled());
-                assertTrue(adapter.disable());
-                break;
             case BluetoothAdapter.STATE_TURNING_ON:
                 assertFalse(adapter.isEnabled());
+                start = System.currentTimeMillis();
+                assertTrue(adapter.disable());
+                break;
+            case BluetoothAdapter.STATE_ON:
+                assertTrue(adapter.isEnabled());
+                start = System.currentTimeMillis();
                 assertTrue(adapter.disable());
                 break;
             case BluetoothAdapter.STATE_TURNING_OFF:
@@ -250,7 +449,8 @@
                 mask = 0; // Don't check for received intents since we might have missed them.
                 break;
             default:
-                fail("disable() invalid state: state=" + state);
+                removeReceiver(receiver);
+                fail(String.format("disable() invalid state: state=%d", state));
         }
 
         long s = System.currentTimeMillis();
@@ -258,10 +458,15 @@
             state = adapter.getState();
             if (state == BluetoothAdapter.STATE_OFF) {
                 assertFalse(adapter.isEnabled());
-                if ((mReceiver.getFiredFlags() & mask) == mask) {
-                    mReceiver.resetFiredFlags();
-                    writeOutput(String.format("disable() completed in %d ms",
-                            (System.currentTimeMillis() - s)));
+                if ((receiver.getFiredFlags() & mask) == mask) {
+                    long finish = receiver.getCompletedTime();
+                    if (start != -1 && finish != -1) {
+                        writeOutput(String.format("disable() completed in %d ms",
+                                (finish - start)));
+                    } else {
+                        writeOutput("disable() completed");
+                    }
+                    removeReceiver(receiver);
                     return;
                 }
             } else {
@@ -271,15 +476,14 @@
             sleep(POLL_TIME);
         }
 
-        int firedFlags = mReceiver.getFiredFlags();
-        mReceiver.resetFiredFlags();
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
         fail(String.format("disable() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
                 state, BluetoothAdapter.STATE_OFF, firedFlags, mask));
     }
 
     public void discoverable(BluetoothAdapter adapter) {
-        int mask = SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG;
-        mReceiver.resetFiredFlags();
+        int mask = BluetoothReceiver.SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG;
 
         if (!adapter.isEnabled()) {
             fail("discoverable() bluetooth not enabled");
@@ -290,35 +494,36 @@
             return;
         }
 
-        assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+        BluetoothReceiver receiver = getBluetoothReceiver(mask);
+
+        assertEquals(BluetoothAdapter.SCAN_MODE_CONNECTABLE, scanMode);
+        long start = System.currentTimeMillis();
         assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
 
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < SET_SCAN_MODE_TIMEOUT) {
+        while (System.currentTimeMillis() - start < SET_SCAN_MODE_TIMEOUT) {
             scanMode = adapter.getScanMode();
             if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
-                if ((mReceiver.getFiredFlags() & mask) == mask) {
-                    mReceiver.resetFiredFlags();
+                if ((receiver.getFiredFlags() & mask) == mask) {
                     writeOutput(String.format("discoverable() completed in %d ms",
-                            (System.currentTimeMillis() - s)));
+                            (receiver.getCompletedTime() - start)));
+                    removeReceiver(receiver);
                     return;
                 }
             } else {
-                assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+                assertEquals(BluetoothAdapter.SCAN_MODE_CONNECTABLE, scanMode);
             }
             sleep(POLL_TIME);
         }
 
-        int firedFlags = mReceiver.getFiredFlags();
-        mReceiver.resetFiredFlags();
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
         fail(String.format("discoverable() timeout: scanMode=%d (expected %d), flags=0x%x "
                 + "(expected 0x%x)", scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE,
                 firedFlags, mask));
     }
 
     public void undiscoverable(BluetoothAdapter adapter) {
-        int mask = SCAN_MODE_CONNECTABLE_FLAG;
-        mReceiver.resetFiredFlags();
+        int mask = BluetoothReceiver.SCAN_MODE_CONNECTABLE_FLAG;
 
         if (!adapter.isEnabled()) {
             fail("undiscoverable() bluetooth not enabled");
@@ -329,35 +534,36 @@
             return;
         }
 
-        assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+        BluetoothReceiver receiver = getBluetoothReceiver(mask);
+
+        assertEquals(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, scanMode);
+        long start = System.currentTimeMillis();
         assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE));
 
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < SET_SCAN_MODE_TIMEOUT) {
+        while (System.currentTimeMillis() - start < SET_SCAN_MODE_TIMEOUT) {
             scanMode = adapter.getScanMode();
             if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
-                if ((mReceiver.getFiredFlags() & mask) == mask) {
-                    mReceiver.resetFiredFlags();
+                if ((receiver.getFiredFlags() & mask) == mask) {
                     writeOutput(String.format("undiscoverable() completed in %d ms",
-                            (System.currentTimeMillis() - s)));
+                            (receiver.getCompletedTime() - start)));
+                    removeReceiver(receiver);
                     return;
                 }
             } else {
-                assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+                assertEquals(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, scanMode);
             }
             sleep(POLL_TIME);
         }
 
-        int firedFlags = mReceiver.getFiredFlags();
-        mReceiver.resetFiredFlags();
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
         fail(String.format("undiscoverable() timeout: scanMode=%d (expected %d), flags=0x%x "
                 + "(expected 0x%x)", scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE, firedFlags,
                 mask));
     }
 
     public void startScan(BluetoothAdapter adapter) {
-        int mask = DISCOVERY_STARTED_FLAG;
-        mReceiver.resetFiredFlags();
+        int mask = BluetoothReceiver.DISCOVERY_STARTED_FLAG;
 
         if (!adapter.isEnabled()) {
             fail("startScan() bluetooth not enabled");
@@ -367,28 +573,29 @@
             return;
         }
 
+        BluetoothReceiver receiver = getBluetoothReceiver(mask);
+
+        long start = System.currentTimeMillis();
         assertTrue(adapter.startDiscovery());
 
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < START_DISCOVERY_TIMEOUT) {
-            if (adapter.isDiscovering() && ((mReceiver.getFiredFlags() & mask) == mask)) {
-                mReceiver.resetFiredFlags();
+        while (System.currentTimeMillis() - start < START_DISCOVERY_TIMEOUT) {
+            if (adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
                 writeOutput(String.format("startScan() completed in %d ms",
-                        (System.currentTimeMillis() - s)));
+                        (receiver.getCompletedTime() - start)));
+                removeReceiver(receiver);
                 return;
             }
             sleep(POLL_TIME);
         }
 
-        int firedFlags = mReceiver.getFiredFlags();
-        mReceiver.resetFiredFlags();
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
         fail(String.format("startScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)",
                 adapter.isDiscovering(), firedFlags, mask));
     }
 
     public void stopScan(BluetoothAdapter adapter) {
-        int mask = DISCOVERY_FINISHED_FLAG;
-        mReceiver.resetFiredFlags();
+        int mask = BluetoothReceiver.DISCOVERY_FINISHED_FLAG;
 
         if (!adapter.isEnabled()) {
             fail("stopScan() bluetooth not enabled");
@@ -398,27 +605,277 @@
             return;
         }
 
+        BluetoothReceiver receiver = getBluetoothReceiver(mask);
+
+        long start = System.currentTimeMillis();
         // TODO: put assertTrue() around cancelDiscovery() once it starts returning true.
         adapter.cancelDiscovery();
 
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < CANCEL_DISCOVERY_TIMEOUT) {
-            if (!adapter.isDiscovering() && ((mReceiver.getFiredFlags() & mask) == mask)) {
-                mReceiver.resetFiredFlags();
+        while (System.currentTimeMillis() - start < CANCEL_DISCOVERY_TIMEOUT) {
+            if (!adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
                 writeOutput(String.format("stopScan() completed in %d ms",
-                        (System.currentTimeMillis() - s)));
+                        (receiver.getCompletedTime() - start)));
+                removeReceiver(receiver);
                 return;
             }
             sleep(POLL_TIME);
         }
 
-        int firedFlags = mReceiver.getFiredFlags();
-        mReceiver.resetFiredFlags();
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
         fail(String.format("stopScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)",
                 adapter.isDiscovering(), firedFlags, mask));
 
     }
 
+    public void pair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) {
+        int mask = PairReceiver.STATE_BONDING_FLAG | PairReceiver.STATE_BONDED_FLAG;
+        long start = -1;
+
+        if (!adapter.isEnabled()) {
+            fail("pair() bluetooth not enabled");
+        }
+
+        PairReceiver receiver = getPairReceiver(device, passkey, pin, mask);
+
+        int state = device.getBondState();
+        switch (state) {
+            case BluetoothDevice.BOND_NONE:
+                assertFalse(adapter.getBondedDevices().contains(device));
+                start = System.currentTimeMillis();
+                assertTrue(device.createBond());
+                break;
+            case BluetoothDevice.BOND_BONDING:
+                mask = 0; // Don't check for received intents since we might have missed them.
+                break;
+            case BluetoothDevice.BOND_BONDED:
+                assertTrue(adapter.getBondedDevices().contains(device));
+                return;
+            default:
+                removeReceiver(receiver);
+                fail(String.format("pair() invalid state: device=%s, state=%d", device, state));
+        }
+
+        long s = System.currentTimeMillis();
+        while (System.currentTimeMillis() - s < PAIR_TIMEOUT) {
+            state = device.getBondState();
+            if (state == BluetoothDevice.BOND_BONDED) {
+                assertTrue(adapter.getBondedDevices().contains(device));
+                if ((receiver.getFiredFlags() & mask) == mask) {
+                    long finish = receiver.getCompletedTime();
+                    if (start != -1 && finish != -1) {
+                        writeOutput(String.format("pair() completed in %d ms: device=%s",
+                                (finish - start), device));
+                    } else {
+                        writeOutput(String.format("pair() completed: device=%s", device));
+                    }
+                    removeReceiver(receiver);
+                    return;
+                }
+            }
+            sleep(POLL_TIME);
+        }
+
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
+        fail(String.format("pair() timeout: device=%s, state=%d (expected %d), "
+                + "flags=0x%x (expected 0x%x)", device, state, BluetoothDevice.BOND_BONDED,
+                firedFlags, mask));
+    }
+
+    public void unpair(BluetoothAdapter adapter, BluetoothDevice device) {
+        int mask = PairReceiver.STATE_NONE_FLAG;
+        long start = -1;
+
+        if (!adapter.isEnabled()) {
+            fail("unpair() bluetooth not enabled");
+        }
+
+        PairReceiver receiver = getPairReceiver(device, 0, null, mask);
+
+        int state = device.getBondState();
+        switch (state) {
+            case BluetoothDevice.BOND_NONE:
+                assertFalse(adapter.getBondedDevices().contains(device));
+                removeReceiver(receiver);
+                return;
+            case BluetoothDevice.BOND_BONDING:
+                start = System.currentTimeMillis();
+                assertTrue(device.removeBond());
+                break;
+            case BluetoothDevice.BOND_BONDED:
+                assertTrue(adapter.getBondedDevices().contains(device));
+                start = System.currentTimeMillis();
+                assertTrue(device.removeBond());
+                break;
+            default:
+                removeReceiver(receiver);
+                fail(String.format("unpair() invalid state: device=%s, state=%d", device, state));
+        }
+
+        long s = System.currentTimeMillis();
+        while (System.currentTimeMillis() - s < UNPAIR_TIMEOUT) {
+            if (device.getBondState() == BluetoothDevice.BOND_NONE) {
+                assertFalse(adapter.getBondedDevices().contains(device));
+                if ((receiver.getFiredFlags() & mask) == mask) {
+                    long finish = receiver.getCompletedTime();
+                    if (start != -1 && finish != -1) {
+                        writeOutput(String.format("unpair() completed in %d ms: device=%s",
+                                (finish - start), device));
+                    } else {
+                        writeOutput(String.format("unpair() completed: device=%s", device));
+                    }
+                    removeReceiver(receiver);
+                    return;
+                }
+            }
+        }
+
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
+        fail(String.format("unpair() timeout: device=%s, state=%d (expected %d), "
+                + "flags=0x%x (expected 0x%x)", device, state, BluetoothDevice.BOND_BONDED,
+                firedFlags, mask));
+    }
+
+    public void connectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile) {
+        int mask = (ConnectProfileReceiver.STATE_CONNECTING_FLAG
+                | ConnectProfileReceiver.STATE_CONNECTED_FLAG);
+        long start = -1;
+
+        if (!adapter.isEnabled()) {
+            fail(String.format("connectProfile() bluetooth not enabled: device=%s, profile=%d",
+                    device, profile));
+        }
+
+        if (!adapter.getBondedDevices().contains(device)) {
+            fail(String.format("connectProfile() device not paired: device=%s, profile=%d",
+                    device, profile));
+        }
+
+        BluetoothProfile proxy = connectProxy(adapter, profile);
+        if (proxy == null) {
+            fail(String.format("connectProfile() unknown profile: device=%s, profile=%d",
+                    device, profile));
+        }
+
+        ConnectProfileReceiver receiver = getConnectProfileReceiver(device, profile, mask);
+
+        int state = proxy.getConnectionState(device);
+        switch (state) {
+            case BluetoothProfile.STATE_CONNECTED:
+                removeReceiver(receiver);
+                return;
+            case BluetoothProfile.STATE_CONNECTING:
+                mask = 0; // Don't check for received intents since we might have missed them.
+                break;
+            case BluetoothProfile.STATE_DISCONNECTED:
+            case BluetoothProfile.STATE_DISCONNECTING:
+                start = System.currentTimeMillis();
+                assertTrue(proxy.connect(device));
+                break;
+            default:
+                removeReceiver(receiver);
+                fail(String.format("connectProfile() invalid state: device=%s, profile=%d, "
+                        + "state=%d", device, profile, state));
+        }
+
+        long s = System.currentTimeMillis();
+        while (System.currentTimeMillis() - s < CONNECT_PROFILE_TIMEOUT) {
+            state = proxy.getConnectionState(device);
+            if (state == BluetoothProfile.STATE_CONNECTED) {
+                if ((receiver.getFiredFlags() & mask) == mask) {
+                    long finish = receiver.getCompletedTime();
+                    if (start != -1 && finish != -1) {
+                        writeOutput(String.format("connectProfile() completed in %d ms: "
+                                +"device=%s, profile=%d", (finish - start), device, profile));
+                    } else {
+                        writeOutput(String.format("connectProfile() completed: device=%s, "
+                                + "profile=%d", device, profile));
+                    }
+                    removeReceiver(receiver);
+                    return;
+                }
+            }
+            sleep(POLL_TIME);
+        }
+
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
+        fail(String.format("connectProfile() timeout: device=%s, profile=%s, "
+                + "state=%d (expected %d), flags=0x%x (expected 0x%x)", device, profile, state,
+                BluetoothProfile.STATE_CONNECTED, firedFlags, mask));
+    }
+
+    public void disconnectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile) {
+        int mask = (ConnectProfileReceiver.STATE_DISCONNECTING_FLAG
+                | ConnectProfileReceiver.STATE_DISCONNECTED_FLAG);
+        long start = -1;
+
+        if (!adapter.isEnabled()) {
+            fail(String.format("disconnectProfile() bluetooth not enabled: device=%s, profile=%d",
+                    device, profile));
+        }
+
+        if (!adapter.getBondedDevices().contains(device)) {
+            fail(String.format("disconnectProfile() device not paired: device=%s, profile=%d",
+                    device, profile));
+        }
+
+        BluetoothProfile proxy = connectProxy(adapter, profile);
+        if (proxy == null) {
+            fail(String.format("disconnectProfile() unknown profile: device=%s, profile=%d",
+                    device, profile));
+        }
+
+        ConnectProfileReceiver receiver = getConnectProfileReceiver(device, profile, mask);
+
+        int state = proxy.getConnectionState(device);
+        switch (state) {
+            case BluetoothProfile.STATE_CONNECTED:
+            case BluetoothProfile.STATE_CONNECTING:
+                start = System.currentTimeMillis();
+                assertTrue(proxy.disconnect(device));
+                break;
+            case BluetoothProfile.STATE_DISCONNECTED:
+                removeReceiver(receiver);
+                return;
+            case BluetoothProfile.STATE_DISCONNECTING:
+                mask = 0; // Don't check for received intents since we might have missed them.
+                break;
+            default:
+                removeReceiver(receiver);
+                fail(String.format("disconnectProfile() invalid state: device=%s, profile=%d, "
+                        + "state=%d", device, profile, state));
+        }
+
+        long s = System.currentTimeMillis();
+        while (System.currentTimeMillis() - s < DISCONNECT_PROFILE_TIMEOUT) {
+            state = proxy.getConnectionState(device);
+            if (state == BluetoothProfile.STATE_DISCONNECTED) {
+                if ((receiver.getFiredFlags() & mask) == mask) {
+                    long finish = receiver.getCompletedTime();
+                    if (start != -1 && finish != -1) {
+                        writeOutput(String.format("disconnectProfile() completed in %d ms: "
+                                +"device=%s, profile=%d", (finish - start), device, profile));
+                    } else {
+                        writeOutput(String.format("disconnectProfile() completed: device=%s, "
+                                + "profile=%d", device, profile));
+                    }
+                    removeReceiver(receiver);
+                    return;
+                }
+            }
+            sleep(POLL_TIME);
+        }
+
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
+        fail(String.format("disconnectProfile() timeout: device=%s, profile=%s, "
+                + "state=%d (expected %d), flags=0x%x (expected 0x%x)", device, profile, state,
+                BluetoothProfile.STATE_DISCONNECTED, firedFlags, mask));
+    }
+
     public void writeOutput(String s) {
         Log.i(mTag, s);
         if (mOutputWriter == null) {
@@ -432,6 +889,67 @@
         }
     }
 
+    private BluetoothReceiver getBluetoothReceiver(int expectedFlags) {
+        BluetoothReceiver receiver = new BluetoothReceiver(expectedFlags);
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
+        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
+        filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
+        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+        mContext.registerReceiver(receiver, filter);
+        mReceivers.add(receiver);
+        return receiver;
+    }
+
+    private PairReceiver getPairReceiver(BluetoothDevice device, int passkey, byte[] pin,
+            int expectedFlags) {
+        PairReceiver receiver = new PairReceiver(device, passkey, pin, expectedFlags);
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
+        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
+        mContext.registerReceiver(receiver, filter);
+        mReceivers.add(receiver);
+        return receiver;
+    }
+
+    private ConnectProfileReceiver getConnectProfileReceiver(BluetoothDevice device, int profile,
+            int expectedFlags) {
+        ConnectProfileReceiver receiver = new ConnectProfileReceiver(device, profile,
+                expectedFlags);
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
+        filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
+        mContext.registerReceiver(receiver, filter);
+        mReceivers.add(receiver);
+        return receiver;
+    }
+
+    private void removeReceiver(BroadcastReceiver receiver) {
+        mContext.unregisterReceiver(receiver);
+        mReceivers.remove(receiver);
+    }
+
+    private BluetoothProfile connectProxy(BluetoothAdapter adapter, int profile) {
+        adapter.getProfileProxy(mContext, mServiceListener, profile);
+        long s = System.currentTimeMillis();
+        switch (profile) {
+            case BluetoothProfile.A2DP:
+                while (mA2dp != null
+                        && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+                    sleep(POLL_TIME);
+                }
+                return mA2dp;
+            case BluetoothProfile.HEADSET:
+                while (mHeadset != null
+                        && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+                    sleep(POLL_TIME);
+                }
+                return mHeadset;
+            default:
+                return null;
+        }
+    }
+
     private void sleep(long time) {
         try {
             Thread.sleep(time);
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 6c08ce5..f8ad5cc 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -194,11 +194,15 @@
         mRS.nAllocationRead(mID, d);
     }
 
-    public void resize(int dimX) {
+    public synchronized void resize(int dimX) {
         if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) {
             throw new IllegalStateException("Resize only support for 1D allocations at this time.");
         }
         mRS.nAllocationResize1D(mID, dimX);
+
+        int typeID = mRS.nAllocationGetType(mID);
+        mType = new Type(typeID, mRS);
+        mType.updateFromNative();
     }
 
     /*
diff --git a/graphics/java/android/renderscript/FileA3D.java b/graphics/java/android/renderscript/FileA3D.java
index 7548878..fc74fc4 100644
--- a/graphics/java/android/renderscript/FileA3D.java
+++ b/graphics/java/android/renderscript/FileA3D.java
@@ -141,9 +141,11 @@
     }
 
     IndexEntry[] mFileEntries;
+    InputStream mInputStream;
 
-    FileA3D(int id, RenderScript rs) {
+    FileA3D(int id, RenderScript rs, InputStream stream) {
         super(id, rs);
+        mInputStream = stream;
     }
 
     private void initEntries() {
@@ -193,20 +195,12 @@
             if(fileId == 0) {
                 throw new IllegalStateException("Load failed.");
             }
-            FileA3D fa3d = new FileA3D(fileId, rs);
+            FileA3D fa3d = new FileA3D(fileId, rs, is);
             fa3d.initEntries();
             return fa3d;
 
         } catch (Exception e) {
             // Ignore
-        } finally {
-            if (is != null) {
-                try {
-                    is.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
         }
 
         return null;
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 53a33e4..430789a 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -112,12 +112,10 @@
 
     public static class FieldBase {
         protected Element mElement;
-        protected Type mType;
         protected Allocation mAllocation;
 
         protected void init(RenderScript rs, int dimx) {
             mAllocation = Allocation.createSized(rs, mElement, dimx);
-            mType = mAllocation.getType();
         }
 
         protected FieldBase() {
@@ -128,7 +126,7 @@
         }
 
         public Type getType() {
-            return mType;
+            return mAllocation.getType();
         }
 
         public Allocation getAllocation() {
@@ -138,19 +136,6 @@
         //@Override
         public void updateAllocation() {
         }
-
-
-        //
-        /*
-        public class ScriptField_UserField
-            extends android.renderscript.Script.FieldBase {
-
-            protected
-
-        }
-
-        */
-
     }
 }
 
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 16d5bfe..b0faacc 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -104,7 +104,10 @@
 {
     LOG_API("nGetName, con(%p), obj(%p)", con, (void *)obj);
     const char *name = NULL;
-    rsGetName(con, (void *)obj, &name);
+    rsaGetName(con, (void *)obj, &name);
+    if(name == NULL || strlen(name) == 0) {
+        return NULL;
+    }
     return _env->NewStringUTF(name);
 }
 
@@ -306,7 +309,7 @@
     assert(dataSize == 5);
 
     uint32_t elementData[5];
-    rsElementGetNativeData(con, (RsElement)id, elementData, dataSize);
+    rsaElementGetNativeData(con, (RsElement)id, elementData, dataSize);
 
     for(jint i = 0; i < dataSize; i ++) {
         _env->SetIntArrayRegion(_elementData, i, 1, (const jint*)&elementData[i]);
@@ -323,7 +326,7 @@
     uint32_t *ids = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
     const char **names = (const char **)malloc((uint32_t)dataSize * sizeof(const char *));
 
-    rsElementGetSubElements(con, (RsElement)id, ids, names, (uint32_t)dataSize);
+    rsaElementGetSubElements(con, (RsElement)id, ids, names, (uint32_t)dataSize);
 
     for(jint i = 0; i < dataSize; i++) {
         _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
@@ -364,7 +367,7 @@
     LOG_API("nTypeCreate, con(%p)", con);
 
     uint32_t typeData[6];
-    rsTypeGetNativeData(con, (RsType)id, typeData, 6);
+    rsaTypeGetNativeData(con, (RsType)id, typeData, 6);
 
     for(jint i = 0; i < elementCount; i ++) {
         _env->SetIntArrayRegion(_typeData, i, 1, (const jint*)&typeData[i]);
@@ -377,7 +380,7 @@
 nAllocationCreateTyped(JNIEnv *_env, jobject _this, RsContext con, jint e)
 {
     LOG_API("nAllocationCreateTyped, con(%p), e(%p)", con, (RsElement)e);
-    return (jint) rsAllocationCreateTyped(con, (RsElement)e);
+    return (jint) rsaAllocationCreateTyped(con, (RsElement)e);
 }
 
 static void
@@ -428,7 +431,7 @@
         const int w = bitmap.width();
         const int h = bitmap.height();
         const void* ptr = bitmap.getPixels();
-        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
+        jint id = (jint)rsaAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
         bitmap.unlockPixels();
         return id;
     }
@@ -488,7 +491,7 @@
         const int w = bitmap.width();
         const int h = bitmap.height();
         const void* ptr = bitmap.getPixels();
-        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
+        jint id = (jint)rsaAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
         bitmap.unlockPixels();
         return id;
     }
@@ -590,7 +593,7 @@
 nAllocationGetType(JNIEnv *_env, jobject _this, RsContext con, jint a)
 {
     LOG_API("nAllocationGetType, con(%p), a(%p)", con, (RsAllocation)a);
-    return (jint) rsAllocationGetType(con, (RsAllocation)a);
+    return (jint) rsaAllocationGetType(con, (RsAllocation)a);
 }
 
 static void
@@ -616,7 +619,7 @@
 
     Asset* asset = reinterpret_cast<Asset*>(native_asset);
 
-    jint id = (jint)rsFileA3DCreateFromAssetStream(con, asset->getBuffer(false), asset->getLength());
+    jint id = (jint)rsaFileA3DCreateFromAssetStream(con, asset->getBuffer(false), asset->getLength());
     return id;
 }
 
@@ -624,7 +627,7 @@
 nFileA3DGetNumIndexEntries(JNIEnv *_env, jobject _this, RsContext con, jint fileA3D)
 {
     int32_t numEntries = 0;
-    rsFileA3DGetNumIndexEntries(con, &numEntries, (RsFile)fileA3D);
+    rsaFileA3DGetNumIndexEntries(con, &numEntries, (RsFile)fileA3D);
     return numEntries;
 }
 
@@ -634,7 +637,7 @@
     LOGV("______nFileA3D %u", (uint32_t) fileA3D);
     RsFileIndexEntry *fileEntries = (RsFileIndexEntry*)malloc((uint32_t)numEntries * sizeof(RsFileIndexEntry));
 
-    rsFileA3DGetIndexEntries(con, fileEntries, (uint32_t)numEntries, (RsFile)fileA3D);
+    rsaFileA3DGetIndexEntries(con, fileEntries, (uint32_t)numEntries, (RsFile)fileA3D);
 
     for(jint i = 0; i < numEntries; i ++) {
         _env->SetObjectArrayElement(_entries, i, _env->NewStringUTF(fileEntries[i].objectName));
@@ -648,7 +651,7 @@
 nFileA3DGetEntryByIndex(JNIEnv *_env, jobject _this, RsContext con, jint fileA3D, jint index)
 {
     LOGV("______nFileA3D %u", (uint32_t) fileA3D);
-    jint id = (jint)rsFileA3DGetEntryByIndex(con, (uint32_t)index, (RsFile)fileA3D);
+    jint id = (jint)rsaFileA3DGetEntryByIndex(con, (uint32_t)index, (RsFile)fileA3D);
     return id;
 }
 
@@ -1166,7 +1169,7 @@
 {
     LOG_API("nMeshGetVertexBufferCount, con(%p), Mesh(%p)", con, (RsMesh)mesh);
     jint vtxCount = 0;
-    rsMeshGetVertexBufferCount(con, (RsMesh)mesh, &vtxCount);
+    rsaMeshGetVertexBufferCount(con, (RsMesh)mesh, &vtxCount);
     return vtxCount;
 }
 
@@ -1175,7 +1178,7 @@
 {
     LOG_API("nMeshGetIndexCount, con(%p), Mesh(%p)", con, (RsMesh)mesh);
     jint idxCount = 0;
-    rsMeshGetIndexCount(con, (RsMesh)mesh, &idxCount);
+    rsaMeshGetIndexCount(con, (RsMesh)mesh, &idxCount);
     return idxCount;
 }
 
@@ -1185,7 +1188,7 @@
     LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", con, (RsMesh)mesh);
 
     RsAllocation *allocs = (RsAllocation*)malloc((uint32_t)numVtxIDs * sizeof(RsAllocation));
-    rsMeshGetVertices(con, (RsMesh)mesh, allocs, (uint32_t)numVtxIDs);
+    rsaMeshGetVertices(con, (RsMesh)mesh, allocs, (uint32_t)numVtxIDs);
 
     for(jint i = 0; i < numVtxIDs; i ++) {
         _env->SetIntArrayRegion(_ids, i, 1, (const jint*)&allocs[i]);
@@ -1202,7 +1205,7 @@
     RsAllocation *allocs = (RsAllocation*)malloc((uint32_t)numIndices * sizeof(RsAllocation));
     uint32_t *prims= (uint32_t*)malloc((uint32_t)numIndices * sizeof(uint32_t));
 
-    rsMeshGetIndices(con, (RsMesh)mesh, allocs, prims, (uint32_t)numIndices);
+    rsaMeshGetIndices(con, (RsMesh)mesh, allocs, prims, (uint32_t)numIndices);
 
     for(jint i = 0; i < numIndices; i ++) {
         _env->SetIntArrayRegion(_idxIds, i, 1, (const jint*)&allocs[i]);
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index 738f62a..a5591ba 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -1046,6 +1046,9 @@
     // Splitting motion events across windows.
     MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
 
+    // Reset and drop everything the dispatcher is doing.
+    void resetAndDropEverythingLocked(const char* reason);
+
     // Dump state.
     void dumpDispatchStateLocked(String8& dump);
     void logDispatchStateLocked();
diff --git a/libs/binder/CursorWindow.cpp b/libs/binder/CursorWindow.cpp
index bdd4dd6..fbba281 100644
--- a/libs/binder/CursorWindow.cpp
+++ b/libs/binder/CursorWindow.cpp
@@ -115,7 +115,7 @@
     uint32_t fieldDirOffset = alloc(fieldDirSize);
     if (!fieldDirOffset) {
         mHeader->numRows--;
-        LOGE("The row failed, so back out the new row accounting from allocRowSlot %d", mHeader->numRows);
+        LOG_WINDOW("The row failed, so back out the new row accounting from allocRowSlot %d", mHeader->numRows);
         return NULL;
     }
     field_slot_t * fieldDir = (field_slot_t *)offsetToPtr(fieldDirOffset);
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index e0094d8..0994d82 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -43,6 +43,8 @@
     glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
     glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
 
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+
     mCurrentBuffer = meshBuffer;
 }
 
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index aff5366..ca22867 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -23,6 +23,7 @@
 
 #include <utils/Singleton.h>
 
+#include "Extensions.h"
 #include "FontRenderer.h"
 #include "GammaFontRenderer.h"
 #include "TextureCache.h"
@@ -93,8 +94,15 @@
     GLenum lastDstMode;
     Program* currentProgram;
 
+    // VBO to draw with
     GLuint meshBuffer;
 
+    // GL extensions
+    Extensions extensions;
+
+    // Misc
+    GLint maxTextureSize;
+
     TextureCache textureCache;
     LayerCache layerCache;
     GradientCache gradientCache;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 8592511..b167131 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -107,8 +107,6 @@
     memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
 
     mFirstSnapshot = new Snapshot;
-
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
@@ -129,6 +127,8 @@
 
     mFirstSnapshot->height = height;
     mFirstSnapshot->viewport.set(0, 0, width, height);
+
+    mDirtyClip = false;
 }
 
 void OpenGLRenderer::prepare(bool opaque) {
@@ -139,16 +139,18 @@
     glViewport(0, 0, mWidth, mHeight);
 
     glDisable(GL_DITHER);
-    glDisable(GL_SCISSOR_TEST);
 
     if (!opaque) {
+        glDisable(GL_SCISSOR_TEST);
         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         glClear(GL_COLOR_BUFFER_BIT);
+        glEnable(GL_SCISSOR_TEST);
+    } else {
+        glEnable(GL_SCISSOR_TEST);
+        glScissor(0, 0, mWidth, mHeight);
+        dirtyClip();
     }
 
-    glEnable(GL_SCISSOR_TEST);
-    glScissor(0, 0, mWidth, mHeight);
-
     mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
 }
 
@@ -175,7 +177,7 @@
     glViewport(0, 0, mSnapshot->viewport.getWidth(), mSnapshot->viewport.getHeight());
 
     glEnable(GL_SCISSOR_TEST);
-    setScissorFromClip();
+    dirtyClip();
 
     glDisable(GL_DITHER);
 
@@ -241,7 +243,7 @@
     }
 
     if (restoreClip) {
-        setScissorFromClip();
+        dirtyClip();
     }
 
     return restoreClip;
@@ -261,7 +263,7 @@
 
     if (p) {
         alpha = p->getAlpha();
-        if (!mExtensions.hasFramebufferFetch()) {
+        if (!mCaches.extensions.hasFramebufferFetch()) {
             const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
             if (!isMode) {
                 // Assume SRC_OVER
@@ -371,8 +373,8 @@
         bounds.intersect(snapshot->previous->viewport);
     }
 
-    if (bounds.isEmpty() || bounds.getWidth() > mMaxTextureSize ||
-            bounds.getHeight() > mMaxTextureSize) {
+    if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
+            bounds.getHeight() > mCaches.maxTextureSize) {
         snapshot->invisible = true;
     } else {
         // TODO: Should take the mode into account
@@ -448,7 +450,7 @@
         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         glClear(GL_COLOR_BUFFER_BIT);
 
-        setScissorFromClip();
+        dirtyClip();
 
         // Change the ortho projection
         glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
@@ -506,6 +508,7 @@
     mCaches.unbindMeshBuffer();
     resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom);
 
+    glActiveTexture(gTextureUnits[0]);
     if (fboLayer) {
         drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
                 layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
@@ -528,6 +531,8 @@
         mCaches.fboCache.put(current->fbo);
     }
 
+    dirtyClip();
+
     // Failing to add the layer to the cache should happen only if the layer is too large
     if (!mCaches.layerCache.put(layer)) {
         LAYER_LOGD("Deleting layer");
@@ -536,6 +541,13 @@
     }
 }
 
+void OpenGLRenderer::setupDraw() {
+    clearLayerRegions();
+    if (mDirtyClip) {
+        setScissorFromClip();
+    }
+}
+
 void OpenGLRenderer::clearLayerRegions() {
     if (mLayers.size() == 0 || mSnapshot->invisible) return;
 
@@ -553,7 +565,7 @@
     mLayers.clear();
 
     // Restore the clip
-    setScissorFromClip();
+    dirtyClip();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -602,6 +614,7 @@
     Rect clip(*mSnapshot->clipRect);
     clip.snapToPixelBoundaries();
     glScissor(clip.left, mSnapshot->height - clip.bottom, clip.getWidth(), clip.getHeight());
+    mDirtyClip = false;
 }
 
 const Rect& OpenGLRenderer::getClipBounds() {
@@ -626,7 +639,7 @@
 bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
     bool clipped = mSnapshot->clip(left, top, right, bottom, op);
     if (clipped) {
-        setScissorFromClip();
+        dirtyClip();
     }
     return !mSnapshot->clipRect->isEmpty();
 }
@@ -676,7 +689,7 @@
         return;
     }
 
-    glActiveTexture(GL_TEXTURE0);
+    glActiveTexture(gTextureUnits[0]);
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
@@ -711,7 +724,7 @@
         return;
     }
 
-    glActiveTexture(GL_TEXTURE0);
+    glActiveTexture(gTextureUnits[0]);
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
@@ -749,6 +762,7 @@
     const bool isAA = paint->isAntiAlias();
     if (isAA) {
         GLuint textureUnit = 0;
+        glActiveTexture(gTextureUnits[textureUnit]);
         setupTextureAlpha8(mCaches.line.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a,
                 mode, false, true, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
                 mCaches.line.getMeshBuffer());
@@ -812,7 +826,7 @@
     }
 
     SkXfermode::Mode mode;
-    if (!mExtensions.hasFramebufferFetch()) {
+    if (!mCaches.extensions.hasFramebufferFetch()) {
         const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
         if (!isMode) {
             // Assume SRC_OVER
@@ -869,10 +883,7 @@
     fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
             paint->getTextSize());
 
-    Rect clipRect(*mSnapshot->clipRect);
-    clipRect.snapToPixelBoundaries();
-    glScissor(clipRect.left, mSnapshot->height - clipRect.bottom,
-            clipRect.getWidth(), clipRect.getHeight());
+    setupDraw();
 
     if (mHasShadow) {
         glActiveTexture(gTextureUnits[0]);
@@ -897,7 +908,6 @@
             x, y, r, g, b, a, mode, false, true, NULL, NULL);
 
     const Rect& clip = mSnapshot->getLocalClip();
-    clearLayerRegions();
 
     mCaches.unbindMeshBuffer();
     fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y);
@@ -906,8 +916,6 @@
     glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
 
     drawTextDecorations(text, bytesCount, length, x, y, paint);
-
-    setScissorFromClip();
 }
 
 void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
@@ -939,7 +947,7 @@
 
     setupTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true, true);
 
-    clearLayerRegions();
+    setupDraw();
 
     // Draw the mesh
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -1035,10 +1043,10 @@
 
      if (applyFilters) {
          if (mShader) {
-             mShader->describe(description, mExtensions);
+             mShader->describe(description, mCaches.extensions);
          }
          if (mColorFilter) {
-             mColorFilter->describe(description, mExtensions);
+             mColorFilter->describe(description, mCaches.extensions);
          }
      }
 
@@ -1048,7 +1056,7 @@
      // Build and use the appropriate shader
      useProgram(mCaches.programCache.get(description));
 
-     bindTexture(texture, textureUnit);
+     bindTexture(texture);
      glUniform1i(mCaches.currentProgram->getUniform("sampler"), textureUnit);
 
      int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
@@ -1155,7 +1163,7 @@
 
 void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
         int color, SkXfermode::Mode mode, bool ignoreTransform) {
-    clearLayerRegions();
+    setupDraw();
 
     // If a shader is set, preserve only the alpha
     if (mShader) {
@@ -1184,10 +1192,10 @@
     const bool setColor = description.setColor(r, g, b, a);
 
     if (mShader) {
-        mShader->describe(description, mExtensions);
+        mShader->describe(description, mCaches.extensions);
     }
     if (mColorFilter) {
-        mColorFilter->describe(description, mExtensions);
+        mColorFilter->describe(description, mCaches.extensions);
     }
 
     // Setup the blending mode
@@ -1244,13 +1252,13 @@
         GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
         GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
         bool swapSrcDst, bool ignoreTransform, GLuint vbo) {
-    clearLayerRegions();
+    setupDraw();
 
     ProgramDescription description;
     description.hasTexture = true;
     const bool setColor = description.setColor(alpha, alpha, alpha, alpha);
     if (mColorFilter) {
-        mColorFilter->describe(description, mExtensions);
+        mColorFilter->describe(description, mCaches.extensions);
     }
 
     mModelView.loadTranslate(left, top, 0.0f);
@@ -1318,7 +1326,7 @@
             // These blend modes are not supported by OpenGL directly and have
             // to be implemented using shaders. Since the shader will perform
             // the blending, turn blending off here
-            if (mExtensions.hasFramebufferFetch()) {
+            if (mCaches.extensions.hasFramebufferFetch()) {
                 description.framebufferMode = mode;
                 description.swapSrcDst = swapSrcDst;
             }
@@ -1354,7 +1362,7 @@
 
 void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
     if (paint) {
-        if (!mExtensions.hasFramebufferFetch()) {
+        if (!mCaches.extensions.hasFramebufferFetch()) {
             const bool isMode = SkXfermode::IsMode(paint->getXfermode(), mode);
             if (!isMode) {
                 // Assume SRC_OVER
@@ -1384,16 +1392,9 @@
     return mode->fMode;
 }
 
-void OpenGLRenderer::bindTexture(GLuint texture, GLuint textureUnit) {
-    glActiveTexture(gTextureUnits[textureUnit]);
-    glBindTexture(GL_TEXTURE_2D, texture);
-}
-
-void OpenGLRenderer::setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT,
-        GLuint textureUnit) {
+void OpenGLRenderer::setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT) {
     bool bound = false;
     if (wrapS != texture->wrapS) {
-        glActiveTexture(gTextureUnits[textureUnit]);
         glBindTexture(GL_TEXTURE_2D, texture->id);
         bound = true;
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
@@ -1401,7 +1402,6 @@
     }
     if (wrapT != texture->wrapT) {
         if (!bound) {
-            glActiveTexture(gTextureUnits[textureUnit]);
             glBindTexture(GL_TEXTURE_2D, texture->id);
         }
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 07188d4..3492d2c 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -259,7 +259,8 @@
             bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0);
 
     /**
-     * Prepares the renderer to draw the specified shadow.
+     * Prepares the renderer to draw the specified shadow. The active texture
+     * unit must be 0 and the other units must be unbound.
      *
      * @param texture The shadow texture
      * @param x The x coordinate of the shadow
@@ -360,11 +361,18 @@
     inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
 
     /**
-     * Binds the specified texture to the specified texture unit.
+     * Binds the specified texture. The texture unit must have been selected
+     * prior to calling this method.
      */
-    inline void bindTexture(GLuint texture, GLuint textureUnit = 0);
-    inline void setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT,
-            GLuint textureUnit = 0);
+    inline void bindTexture(GLuint texture) {
+        glBindTexture(GL_TEXTURE_2D, texture);
+    }
+
+    /**
+     * Sets the wrap modes for the specified texture. The wrap modes are modified
+     * only when needed.
+     */
+    inline void setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT);
 
     /**
      * Enable or disable blending as necessary. This function sets the appropriate
@@ -391,6 +399,18 @@
      */
     inline bool useProgram(Program* program);
 
+    /**
+     * Invoked before any drawing operation. This sets required state.
+     */
+    void setupDraw();
+
+    /**
+     * Should be invoked every time the glScissor is modified.
+     */
+    inline void dirtyClip() {
+        mDirtyClip = true;
+    }
+
     // Dimensions of the drawing surface
     int mWidth, mHeight;
 
@@ -416,9 +436,6 @@
     // Used to draw textured quads
     TextureVertex mMeshVertices[4];
 
-    // GL extensions
-    Extensions mExtensions;
-
     // Drop shadow
     bool mHasShadow;
     float mShadowRadius;
@@ -432,12 +449,12 @@
     // List of rectangles to clear due to calls to saveLayer()
     Vector<Rect*> mLayers;
 
-    // Misc
-    GLint mMaxTextureSize;
-
     // Indentity matrix
     const mat4 mIdentity;
 
+    // Indicates whether the clip must be restored
+    bool mDirtyClip;
+
     friend class DisplayListRenderer;
 
 }; // class OpenGLRenderer
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index d078d46..8c2081d 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -286,11 +286,31 @@
 
 } RsScriptCall;
 
+// A3D loading and object update code.
+// Should only be called at object creation, not thread safe
+RsObjectBase rsaFileA3DGetEntryByIndex(RsContext, uint32_t idx, RsFile);
+RsFile rsaFileA3DCreateFromAssetStream(RsContext, const void *data, uint32_t len);
+void rsaFileA3DGetNumIndexEntries(RsContext, int32_t *numEntries, RsFile);
+void rsaFileA3DGetIndexEntries(RsContext, RsFileIndexEntry *fileEntries,uint32_t numEntries, RsFile);
+void rsaGetName(RsContext, void * obj, const char **name);
+// Mesh update functions
+void rsaMeshGetVertexBufferCount(RsContext, RsMesh, int32_t *vtxCount);
+void rsaMeshGetIndexCount(RsContext, RsMesh, int32_t *idxCount);
+void rsaMeshGetVertices(RsContext, RsMesh, RsAllocation *vtxData, uint32_t vtxDataCount);
+void rsaMeshGetIndices(RsContext, RsMesh, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount);
+// Allocation update
+const void* rsaAllocationGetType(RsContext con, RsAllocation va);
+// Type update
+void rsaTypeGetNativeData(RsContext, RsType, uint32_t *typeData, uint32_t typeDataSize);
+// Element update
+void rsaElementGetNativeData(RsContext, RsElement, uint32_t *elemData, uint32_t elemDataSize);
+void rsaElementGetSubElements(RsContext, RsElement, uint32_t *ids, const char **names, uint32_t dataSize);
 
 // Async commands for returning new IDS
 RsType rsaTypeCreate(RsContext, RsElement, uint32_t dimCount,
                      const RsDimension *dims, const uint32_t *vals);
-
+RsAllocation rsaAllocationCreateTyped(RsContext rsc, RsType vtype);
+RsAllocation rsaAllocationCreateFromBitmap(RsContext con, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data);
 
 #ifndef NO_RS_FUNCS
 #include "rsgApiFuncDecl.h"
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index eb2942e..14809e9 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -58,11 +58,6 @@
 	param size_t len
 	}
 
-GetName {
-	param void *obj
-	param const char **name
-	}
-
 ObjDestroy {
 	param RsAsyncVoidPtr objPtr
 	}
@@ -84,37 +79,6 @@
 	ret RsElement
 	}
 
-ElementGetNativeData {
-	param RsElement elem
-	param uint32_t *elemData
-	param uint32_t elemDataSize
-	}
-
-ElementGetSubElements {
-	param RsElement elem
-	param uint32_t *ids
-	param const char **names
-	param uint32_t dataSize
-	}
-
-
-TypeGetNativeData {
-	param RsType type
-	param uint32_t * typeData
-	param uint32_t typeDataSize
-	}
-
-AllocationCreateTyped {
-	param RsType type
-	ret RsAllocation
-	}
-
-AllocationCreateSized {
-	param RsElement e
-	param size_t count
-	ret RsAllocation
-	}
-
 AllocationUpdateFromBitmap {
 	param RsAllocation alloc
 	param RsElement srcFmt
@@ -129,17 +93,6 @@
 	ret RsAllocation
 	}
 
-AllocationCreateFromBitmap {
-	param uint32_t width
-	param uint32_t height
-	param RsElement dstFmt
-	param RsElement srcFmt
-	param bool genMips
-	param const void * data
-	ret RsAllocation
-	}
-
-
 AllocationUploadToTexture {
 	param RsAllocation alloc
 	param bool genMipMaps
@@ -259,11 +212,6 @@
 	param const void *data
 	}
 
-AllocationGetType {
-	param RsAllocation va
-	ret const void*
-	}
-
 AllocationResize1D {
 	param RsAllocation va
 	param uint32_t dimX
@@ -455,35 +403,12 @@
 	ret RsProgramVertex
 	}
 
-FileA3DCreateFromAssetStream {
-	param const void * data
-	param size_t len
-	ret RsFile
-	}
-
 FileOpen {
 	ret RsFile
 	param const char *name
 	param size_t len
 	}
 
-FileA3DGetNumIndexEntries {
-	param int32_t * numEntries
-	param RsFile file
-	}
-
-FileA3DGetIndexEntries {
-	param RsFileIndexEntry * fileEntries
-	param uint32_t numEntries
-	param RsFile fileA3D
-	}
-
-FileA3DGetEntryByIndex {
-	param uint32_t index
-	param RsFile file
-	ret RsObjectBase
-	}
-
 FontCreateFromFile {
 	param const char *name
 	param uint32_t fontSize
@@ -510,29 +435,6 @@
 	param uint32_t slot
 	}
 
-MeshGetVertexBufferCount {
-	param RsMesh mesh
-	param int32_t *numVtx
-	}
-
-MeshGetIndexCount {
-	param RsMesh mesh
-	param int32_t *numIdx
-	}
-
-MeshGetVertices {
-	param RsMesh mv
-	param RsAllocation *vtxData
-	param uint32_t vtxDataCount
-	}
-
-MeshGetIndices {
-	param RsMesh mv
-	param RsAllocation *va
-	param uint32_t *primType
-	param uint32_t idxDataCount
-	}
-
 AnimationCreate {
 	param const float *inValues
 	param const float *outValues
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index fc41a72..b74fa8e 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -563,24 +563,6 @@
 namespace android {
 namespace renderscript {
 
-RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype)
-{
-    const Type * type = static_cast<const Type *>(vtype);
-
-    Allocation * alloc = new Allocation(rsc, type);
-    alloc->incUserRef();
-    return alloc;
-}
-
-RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count)
-{
-    Type * type = new Type(rsc);
-    type->setDimX(count);
-    type->setElement(static_cast<Element *>(e));
-    type->compute();
-    return rsi_AllocationCreateTyped(rsc, type);
-}
-
 void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel)
 {
     Allocation *alloc = static_cast<Allocation *>(va);
@@ -786,42 +768,6 @@
     }
 }
 
-RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data)
-{
-    const Element *src = static_cast<const Element *>(_src);
-    const Element *dst = static_cast<const Element *>(_dst);
-
-    //LOGE("%p rsi_AllocationCreateFromBitmap %i %i %i", rsc, w, h, genMips);
-    RsDimension dims[] = {RS_DIMENSION_X, RS_DIMENSION_Y, RS_DIMENSION_LOD};
-    uint32_t dimValues[] = {w, h, genMips};
-    RsType type = rsaTypeCreate(rsc, _dst, 3, dims, dimValues);
-
-    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type);
-    Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
-    if (texAlloc == NULL) {
-        LOGE("Memory allocation failure");
-        return NULL;
-    }
-
-    ElementConverter_t cvt = pickConverter(dst, src);
-    if (cvt) {
-        cvt(texAlloc->getPtr(), data, w * h);
-        if (genMips) {
-            Adapter2D adapt(rsc, texAlloc);
-            Adapter2D adapt2(rsc, texAlloc);
-            for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
-                adapt.setLOD(lod);
-                adapt2.setLOD(lod + 1);
-                mip(adapt2, adapt);
-            }
-        }
-    } else {
-        rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
-    }
-
-    return texAlloc;
-}
-
 void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes)
 {
     Allocation *a = static_cast<Allocation *>(va);
@@ -870,7 +816,12 @@
     a->resize2D(rsc, dimX, dimY);
 }
 
-const void* rsi_AllocationGetType(Context *rsc, RsAllocation va)
+#endif //ANDROID_RS_BUILD_FOR_HOST
+
+}
+}
+
+const void * rsaAllocationGetType(RsContext con, RsAllocation va)
 {
     Allocation *a = static_cast<Allocation *>(va);
     a->getType()->incUserRef();
@@ -878,7 +829,47 @@
     return a->getType();
 }
 
-#endif //ANDROID_RS_BUILD_FOR_HOST
-
+RsAllocation rsaAllocationCreateTyped(RsContext con, RsType vtype)
+{
+    Context *rsc = static_cast<Context *>(con);
+    Allocation * alloc = new Allocation(rsc, static_cast<Type *>(vtype));
+    alloc->incUserRef();
+    return alloc;
 }
+
+RsAllocation rsaAllocationCreateFromBitmap(RsContext con, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data)
+{
+    Context *rsc = static_cast<Context *>(con);
+    const Element *src = static_cast<const Element *>(_src);
+    const Element *dst = static_cast<const Element *>(_dst);
+
+    //LOGE("%p rsi_AllocationCreateFromBitmap %i %i %i", rsc, w, h, genMips);
+    RsDimension dims[] = {RS_DIMENSION_X, RS_DIMENSION_Y, RS_DIMENSION_LOD};
+    uint32_t dimValues[] = {w, h, genMips};
+    RsType type = rsaTypeCreate(rsc, _dst, 3, dims, dimValues);
+
+    RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, type);
+    Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
+    if (texAlloc == NULL) {
+        LOGE("Memory allocation failure");
+        return NULL;
+    }
+
+    ElementConverter_t cvt = pickConverter(dst, src);
+    if (cvt) {
+        cvt(texAlloc->getPtr(), data, w * h);
+        if (genMips) {
+            Adapter2D adapt(rsc, texAlloc);
+            Adapter2D adapt2(rsc, texAlloc);
+            for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
+                adapt.setLOD(lod);
+                adapt2.setLOD(lod + 1);
+                mip(adapt2, adapt);
+            }
+        }
+    } else {
+        rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
+    }
+
+    return texAlloc;
 }
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 944cd86..3f04585 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -222,6 +222,7 @@
     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors);
 
     mGL.OES_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_OES_texture_npot");
+    mGL.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)mGL.mExtensions, "GL_NV_texture_npot_2D_mipmap");
     mGL.EXT_texture_max_aniso = 1.0f;
     bool hasAniso = NULL != strstr((const char *)mGL.mExtensions, "GL_EXT_texture_filter_anisotropic");
     if(hasAniso) {
@@ -970,12 +971,6 @@
     rsc->assignName(ob, name, len);
 }
 
-void rsi_GetName(Context *rsc, void * obj, const char **name)
-{
-    ObjectBase *ob = static_cast<ObjectBase *>(obj);
-    (*name) = ob->getName();
-}
-
 void rsi_ObjDestroy(Context *rsc, void *optr)
 {
     ObjectBase *ob = static_cast<ObjectBase *>(optr);
@@ -1062,3 +1057,10 @@
     rsc->deinitToClient();
 }
 
+// Only to be called at a3d load time, before object is visible to user
+// not thread safe
+void rsaGetName(RsContext con, void * obj, const char **name)
+{
+    ObjectBase *ob = static_cast<ObjectBase *>(obj);
+    (*name) = ob->getName();
+}
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index dbe2c79..e269d4e 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -190,6 +190,7 @@
     mutable const ObjectBase * mObjHead;
 
     bool ext_OES_texture_npot() const {return mGL.OES_texture_npot;}
+    bool ext_GL_NV_texture_npot_2D_mipmap() const {return mGL.GL_NV_texture_npot_2D_mipmap;}
     float ext_texture_max_aniso() const {return mGL.EXT_texture_max_aniso; }
     uint32_t getMaxFragmentTextures() const {return mGL.mMaxFragmentTextureImageUnits;}
     uint32_t getMaxFragmentUniformVectors() const {return mGL.mMaxFragmentUniformVectors;}
@@ -232,6 +233,7 @@
         int32_t mMaxVertexTextureUnits;
 
         bool OES_texture_npot;
+        bool GL_NV_texture_npot_2D_mipmap;
         float EXT_texture_max_aniso;
     } mGL;
 
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index dc021fc..d207dcf 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -379,7 +379,10 @@
     return (RsElement)e;
 }
 
-void rsi_ElementGetNativeData(Context *rsc, RsElement elem, uint32_t *elemData, uint32_t elemDataSize)
+}
+}
+
+void rsaElementGetNativeData(RsContext con, RsElement elem, uint32_t *elemData, uint32_t elemDataSize)
 {
     rsAssert(elemDataSize == 5);
     // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
@@ -393,18 +396,15 @@
 
 }
 
-void rsi_ElementGetSubElements(Context *rsc, RsElement elem, uint32_t *ids, const char **names, uint32_t dataSize)
+void rsaElementGetSubElements(RsContext con, RsElement elem, uint32_t *ids, const char **names, uint32_t dataSize)
 {
     Element *e = static_cast<Element *>(elem);
     rsAssert(e->getFieldCount() == dataSize);
 
     for(uint32_t i = 0; i < dataSize; i ++) {
+        e->getField(i)->incUserRef();
         ids[i] = (uint32_t)e->getField(i);
         names[i] = e->getFieldName(i);
     }
 
 }
-
-
-}
-}
diff --git a/libs/rs/rsFileA3D.cpp b/libs/rs/rsFileA3D.cpp
index c90edc2..e4c6dbd 100644
--- a/libs/rs/rsFileA3D.cpp
+++ b/libs/rs/rsFileA3D.cpp
@@ -115,19 +115,10 @@
         return false;
     }
 
-    uint8_t *headerData = (uint8_t *)malloc(headerSize);
-    if(!headerData) {
-        return false;
-    }
-
-    memcpy(headerData, localData, headerSize);
-
     // Now open the stream to parse the header
-    IStream headerStream(headerData, false);
+    IStream headerStream(localData, false);
     parseHeader(&headerStream);
 
-    free(headerData);
-
     localData += headerSize;
     lengthRemaining -= headerSize;
 
@@ -145,13 +136,7 @@
     }
 
     // We should know enough to read the file in at this point.
-    mAlloc = malloc(mDataSize);
-    if (!mAlloc) {
-        return false;
-    }
-    mData = (uint8_t *)mAlloc;
-    memcpy(mAlloc, localData, mDataSize);
-
+    mData = (uint8_t *)localData;
     mReadStream = new IStream(mData, mUse64BitOffsets);
 
     return true;
@@ -383,7 +368,41 @@
 namespace android {
 namespace renderscript {
 
-void rsi_FileA3DGetNumIndexEntries(Context *rsc, int32_t *numEntries, RsFile file)
+RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len)
+{
+    FileA3D *fa3d = new FileA3D(rsc);
+
+    FILE *f = fopen("/sdcard/test.a3d", "rb");
+    if (f) {
+        fa3d->load(f);
+        fclose(f);
+        fa3d->incUserRef();
+        return fa3d;
+    }
+    delete fa3d;
+    return NULL;
+}
+
+
+}
+}
+
+RsObjectBase rsaFileA3DGetEntryByIndex(RsContext con, uint32_t index, RsFile file)
+{
+    FileA3D *fa3d = static_cast<FileA3D *>(file);
+    if(!fa3d) {
+        LOGE("Can't load entry. No valid file");
+        return NULL;
+    }
+
+    ObjectBase *obj = fa3d->initializeFromEntry(index);
+    LOGV("Returning object with name %s", obj->getName());
+
+    return obj;
+}
+
+
+void rsaFileA3DGetNumIndexEntries(RsContext con, int32_t *numEntries, RsFile file)
 {
     FileA3D *fa3d = static_cast<FileA3D *>(file);
 
@@ -395,7 +414,7 @@
     }
 }
 
-void rsi_FileA3DGetIndexEntries(Context *rsc, RsFileIndexEntry *fileEntries, uint32_t numEntries, RsFile file)
+void rsaFileA3DGetIndexEntries(RsContext con, RsFileIndexEntry *fileEntries, uint32_t numEntries, RsFile file)
 {
     FileA3D *fa3d = static_cast<FileA3D *>(file);
 
@@ -418,51 +437,17 @@
 
 }
 
-RsObjectBase rsi_FileA3DGetEntryByIndex(Context *rsc, uint32_t index, RsFile file)
-{
-    FileA3D *fa3d = static_cast<FileA3D *>(file);
-    if(!fa3d) {
-        LOGE("Can't load entry. No valid file");
-        return NULL;
-    }
-
-    ObjectBase *obj = fa3d->initializeFromEntry(index);
-    LOGV("Returning object with name %s", obj->getName());
-
-    return obj;
-}
-
-RsFile rsi_FileA3DCreateFromAssetStream(Context *rsc, const void *data, uint32_t len)
+RsFile rsaFileA3DCreateFromAssetStream(RsContext con, const void *data, uint32_t len)
 {
     if (data == NULL) {
         LOGE("File load failed. Asset stream is NULL");
         return NULL;
     }
 
+    Context *rsc = static_cast<Context *>(con);
     FileA3D *fa3d = new FileA3D(rsc);
-
-    fa3d->load(data, len);
     fa3d->incUserRef();
 
+    fa3d->load(data, len);
     return fa3d;
 }
-
-
-RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len)
-{
-    FileA3D *fa3d = new FileA3D(rsc);
-
-    FILE *f = fopen("/sdcard/test.a3d", "rb");
-    if (f) {
-        fa3d->load(f);
-        fclose(f);
-        fa3d->incUserRef();
-        return fa3d;
-    }
-    delete fa3d;
-    return NULL;
-}
-
-
-}
-}
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index d171a48..9e76215 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -511,10 +511,7 @@
     mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1);
     const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC);
 
-    Type *inputType = new Type(mRSC);
-    inputType->setElement(constInput);
-    inputType->setDimX(1);
-    inputType->compute();
+    Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false);
 
     uint32_t tmp[4];
     tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
@@ -546,11 +543,7 @@
     const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
 
     // We will allocate a texture to initially hold 32 character bitmaps
-    Type *texType = new Type(mRSC);
-    texType->setElement(alphaElem);
-    texType->setDimX(1024);
-    texType->setDimY(256);
-    texType->compute();
+    Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false);
 
     Allocation *cacheAlloc = new Allocation(mRSC, texType);
     mTextTexture.set(cacheAlloc);
@@ -578,11 +571,8 @@
 {
     // Now lets write index data
     const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
-    Type *indexType = new Type(mRSC);
     uint32_t numIndicies = mMaxNumberOfQuads * 6;
-    indexType->setDimX(numIndicies);
-    indexType->setElement(indexElem);
-    indexType->compute();
+    Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false);
 
     Allocation *indexAlloc = new Allocation(mRSC, indexType);
     uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr();
@@ -612,10 +602,9 @@
     mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1);
     const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC);
 
-    Type *vertexDataType = new Type(mRSC);
-    vertexDataType->setDimX(mMaxNumberOfQuads * 4);
-    vertexDataType->setElement(vertexDataElem);
-    vertexDataType->compute();
+    Type *vertexDataType = Type::getType(mRSC, vertexDataElem,
+                                         mMaxNumberOfQuads * 4,
+                                         0, 0, false, false);
 
     Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType);
     mTextMeshPtr = (float*)vertexAlloc->getPtr();
diff --git a/libs/rs/rsMesh.cpp b/libs/rs/rsMesh.cpp
index 761be93..fd604e5 100644
--- a/libs/rs/rsMesh.cpp
+++ b/libs/rs/rsMesh.cpp
@@ -310,19 +310,21 @@
     sm->updateGLPrimitives();
 }
 
-void rsi_MeshGetVertexBufferCount(Context *rsc, RsMesh mv, int32_t *numVtx)
+}}
+
+void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx)
 {
     Mesh *sm = static_cast<Mesh *>(mv);
     *numVtx = sm->mVertexBufferCount;
 }
 
-void rsi_MeshGetIndexCount(Context *rsc, RsMesh mv, int32_t *numIdx)
+void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx)
 {
     Mesh *sm = static_cast<Mesh *>(mv);
     *numIdx = sm->mPrimitivesCount;
 }
 
-void rsi_MeshGetVertices(Context *rsc, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount)
+void rsaMeshGetVertices(RsContext con, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount)
 {
     Mesh *sm = static_cast<Mesh *>(mv);
     rsAssert(vtxDataCount == sm->mVertexBufferCount);
@@ -333,7 +335,7 @@
     }
 }
 
-void rsi_MeshGetIndices(Context *rsc, RsMesh mv, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount)
+void rsaMeshGetIndices(RsContext con, RsMesh mv, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount)
 {
     Mesh *sm = static_cast<Mesh *>(mv);
     rsAssert(idxDataCount == sm->mPrimitivesCount);
@@ -347,8 +349,3 @@
     }
 
 }
-
-
-
-
-}}
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 724172e..44dc042 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -120,8 +120,15 @@
 
 bool ObjectBase::decUserRef() const
 {
-    //LOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount);
     rsAssert(mUserRefCount > 0);
+#if RS_OBJECT_DEBUG
+    LOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount);
+    if (mUserRefCount <= 0) {
+        mStack.dump();
+    }
+#endif
+
+
     if ((android_atomic_dec(&mUserRefCount) <= 1) &&
         (android_atomic_acquire_load(&mSysRefCount) <= 0)) {
         return checkDelete(this);
diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h
index 5f03db5..5cc275a 100644
--- a/libs/rs/rsObjectBase.h
+++ b/libs/rs/rsObjectBase.h
@@ -21,9 +21,7 @@
 
 #define RS_OBJECT_DEBUG 0
 
-#if RS_OBJECT_DEBUG
-    #include <utils/CallStack.h>
-#endif
+#include <utils/CallStack.h>
 
 namespace android {
 namespace renderscript {
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index 33399d5..800854b 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -198,10 +198,7 @@
     rsc->mStateElement.elementBuilderAdd(colorElem, "Color", 1);
     const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc);
 
-    Type *inputType = new Type(rsc);
-    inputType->setElement(constInput);
-    inputType->setDimX(1);
-    inputType->compute();
+    Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false);
 
     uint32_t tmp[4];
     tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index d12439f..4e64008 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -257,10 +257,7 @@
     rsc->mStateElement.elementBuilderAdd(f2Elem, "texture0", 1);
     const Element *attrElem = rsc->mStateElement.elementBuilderCreate(rsc);
 
-    Type *inputType = new Type(rsc);
-    inputType->setElement(constInput);
-    inputType->setDimX(1);
-    inputType->compute();
+    Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false);
 
     String8 shaderString(RS_SHADER_INTERNAL);
     shaderString.append("varying vec4 varColor;\n");
diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
index cfae7b2..cbdc407 100644
--- a/libs/rs/rsSampler.cpp
+++ b/libs/rs/rsSampler.cpp
@@ -76,7 +76,11 @@
     };
 
     if (!rsc->ext_OES_texture_npot() && tex->getType()->getIsNp2()) {
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, transNP[mMinFilter]);
+        if (tex->getHasGraphicsMipmaps() && rsc->ext_GL_NV_texture_npot_2D_mipmap()) {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
+        } else {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, transNP[mMinFilter]);
+        }
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, transNP[mMagFilter]);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, transNP[mWrapS]);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, transNP[mWrapT]);
diff --git a/libs/rs/rsScriptC_LibCL.cpp b/libs/rs/rsScriptC_LibCL.cpp
index ce8e7b2..1b1a752 100644
--- a/libs/rs/rsScriptC_LibCL.cpp
+++ b/libs/rs/rsScriptC_LibCL.cpp
@@ -205,9 +205,9 @@
     { "_Z5asinhf", (void *)&asinhf },
     { "_Z6asinpif", (void *)&SC_asinpi },
     { "_Z4atanf", (void *)&atanf },
-    { "_Z5atan2f", (void *)&atan2f },
+    { "_Z5atan2ff", (void *)&atan2f },
     { "_Z6atanpif", (void *)&SC_atanpi },
-    { "_Z7atan2pif", (void *)&SC_atan2pi },
+    { "_Z7atan2piff", (void *)&SC_atan2pi },
     { "_Z4cbrtf", (void *)&cbrtf },
     { "_Z4ceilf", (void *)&ceilf },
     { "_Z8copysignff", (void *)&copysignf },
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 82ad33e..caaa9f5 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -276,20 +276,12 @@
         return NULL;
     }
 
-    Type *type = new Type(rsc);
-    type->mDimX = stream->loadU32();
-    type->mDimY = stream->loadU32();
-    type->mDimZ = stream->loadU32();
-
-    uint8_t temp = stream->loadU8();
-    type->mDimLOD = temp != 0;
-
-    temp = stream->loadU8();
-    type->mFaces = temp != 0;
-
-    type->setElement(elem);
-
-    return type;
+    uint32_t x = stream->loadU32();
+    uint32_t y = stream->loadU32();
+    uint32_t z = stream->loadU32();
+    uint8_t lod = stream->loadU8();
+    uint8_t faces = stream->loadU8();
+    return Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0 );
 }
 
 bool Type::getIsNp2() const
@@ -325,56 +317,55 @@
     return false;
 }
 
-Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const
+Type * Type::getType(Context *rsc, const Element *e,
+                     uint32_t dimX, uint32_t dimY, uint32_t dimZ,
+                     bool dimLOD, bool dimFaces)
 {
     TypeState * stc = &rsc->mStateType;
+
+    ObjectBase::asyncLock();
     for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
         Type *t = stc->mTypes[ct];
-        if (t->getElement() != mElement.get()) continue;
+        if (t->getElement() != e) continue;
         if (t->getDimX() != dimX) continue;
-        if (t->getDimY() != mDimY) continue;
-        if (t->getDimZ() != mDimZ) continue;
-        if (t->getDimLOD() != mDimLOD) continue;
-        if (t->getDimFaces() != mFaces) continue;
+        if (t->getDimY() != dimY) continue;
+        if (t->getDimZ() != dimZ) continue;
+        if (t->getDimLOD() != dimLOD) continue;
+        if (t->getDimFaces() != dimFaces) continue;
         t->incUserRef();
+        ObjectBase::asyncUnlock();
         return t;
     }
+    ObjectBase::asyncUnlock();
+
 
     Type *nt = new Type(rsc);
-    nt->mElement.set(mElement);
+    nt->mElement.set(e);
     nt->mDimX = dimX;
-    nt->mDimY = mDimY;
-    nt->mDimZ = mDimZ;
-    nt->mDimLOD = mDimLOD;
-    nt->mFaces = mFaces;
+    nt->mDimY = dimY;
+    nt->mDimZ = dimZ;
+    nt->mDimLOD = dimLOD;
+    nt->mFaces = dimFaces;
     nt->compute();
+    nt->incUserRef();
+
+    ObjectBase::asyncLock();
+    stc->mTypes.push(nt);
+    ObjectBase::asyncUnlock();
+
     return nt;
 }
 
+Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const
+{
+    return getType(rsc, mElement.get(), dimX,
+                   mDimY, mDimZ, mDimLOD, mFaces);
+}
+
 Type * Type::cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const
 {
-    TypeState * stc = &rsc->mStateType;
-    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
-        Type *t = stc->mTypes[ct];
-        if (t->getElement() != mElement.get()) continue;
-        if (t->getDimX() != dimX) continue;
-        if (t->getDimY() != dimY) continue;
-        if (t->getDimZ() != mDimZ) continue;
-        if (t->getDimLOD() != mDimLOD) continue;
-        if (t->getDimFaces() != mFaces) continue;
-        t->incUserRef();
-        return t;
-    }
-
-    Type *nt = new Type(rsc);
-    nt->mElement.set(mElement);
-    nt->mDimX = dimX;
-    nt->mDimY = dimY;
-    nt->mDimZ = mDimZ;
-    nt->mDimLOD = mDimLOD;
-    nt->mFaces = mFaces;
-    nt->compute();
-    return nt;
+    return getType(rsc, mElement.get(), dimX, dimY,
+                   mDimZ, mDimLOD, mFaces);
 }
 
 
@@ -383,23 +374,6 @@
 namespace android {
 namespace renderscript {
 
-void rsi_TypeGetNativeData(Context *rsc, RsType type, uint32_t *typeData, uint32_t typeDataSize)
-{
-    rsAssert(typeDataSize == 6);
-    // Pack the data in the follofing way mDimX; mDimY; mDimZ;
-    // mDimLOD; mDimFaces; mElement; into typeData
-    Type *t = static_cast<Type *>(type);
-
-    (*typeData++) = t->getDimX();
-    (*typeData++) = t->getDimY();
-    (*typeData++) = t->getDimZ();
-    (*typeData++) = t->getDimLOD();
-    (*typeData++) = t->getDimFaces() ? 1 : 0;
-    (*typeData++) = (uint32_t)t->getElement();
-
-}
-
-
 }
 }
 
@@ -430,34 +404,21 @@
         }
     }
 
-    ObjectBase::asyncLock();
-    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
-        Type *t = stc->mTypes[ct];
-        if (t->getElement() != e) continue;
-        if (t->getDimX() != dimX) continue;
-        if (t->getDimY() != dimY) continue;
-        if (t->getDimZ() != dimZ) continue;
-        if (t->getDimLOD() != dimLOD) continue;
-        if (t->getDimFaces() != dimFaces) continue;
-        t->incUserRef();
-        ObjectBase::asyncUnlock();
-        return t;
-    }
-    ObjectBase::asyncUnlock();
-
-    Type * st = new Type(rsc);
-    st->incUserRef();
-    st->setDimX(dimX);
-    st->setDimY(dimY);
-    st->setDimZ(dimZ);
-    st->setElement(e);
-    st->setDimLOD(dimLOD);
-    st->setDimFaces(dimFaces);
-    st->compute();
-
-    ObjectBase::asyncLock();
-    stc->mTypes.push(st);
-    ObjectBase::asyncUnlock();
-    return st;
+    return Type::getType(rsc, e, dimX, dimY, dimZ, dimLOD, dimFaces);
 }
 
+void rsaTypeGetNativeData(RsContext con, RsType type, uint32_t *typeData, uint32_t typeDataSize)
+{
+    rsAssert(typeDataSize == 6);
+    // Pack the data in the follofing way mDimX; mDimY; mDimZ;
+    // mDimLOD; mDimFaces; mElement; into typeData
+    Type *t = static_cast<Type *>(type);
+
+    (*typeData++) = t->getDimX();
+    (*typeData++) = t->getDimY();
+    (*typeData++) = t->getDimZ();
+    (*typeData++) = t->getDimLOD();
+    (*typeData++) = t->getDimFaces() ? 1 : 0;
+    (*typeData++) = (uint32_t)t->getElement();
+    t->getElement()->incUserRef();
+}
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 6b89413..0ca5bb6 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -28,9 +28,6 @@
 class Type : public ObjectBase
 {
 public:
-    Type(Context *);
-    virtual ~Type();
-
     Type * createTex2D(const Element *, size_t w, size_t h, bool mip);
 
 
@@ -58,15 +55,6 @@
     uint32_t getLODCount() const {return mLODCount;}
     bool getIsNp2() const;
 
-
-    void setElement(const Element *e) {mElement.set(e);}
-    void setDimX(uint32_t v) {mDimX = v;}
-    void setDimY(uint32_t v) {mDimY = v;}
-    void setDimZ(uint32_t v) {mDimZ = v;}
-    void setDimFaces(bool v) {mFaces = v;}
-    void setDimLOD(bool v) {mDimLOD = v;}
-
-
     void clear();
     void compute();
 
@@ -82,6 +70,10 @@
     Type * cloneAndResize1D(Context *rsc, uint32_t dimX) const;
     Type * cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const;
 
+    static Type * getType(Context *rsc, const Element *e,
+                      uint32_t dimX, uint32_t dimY, uint32_t dimZ,
+                      bool dimLOD, bool dimFaces);
+
 protected:
     struct LOD {
         size_t mX;
@@ -124,10 +116,13 @@
     bool isValidGLComponent(uint32_t fieldIdx);
     void makeGLComponents();
 
+
 protected:
     virtual void preDestroy();
+    virtual ~Type();
 
 private:
+    Type(Context *);
     Type(const Type &);
 };
 
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 4c86ebe..b936c4d 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -1305,6 +1305,9 @@
     }
 
 Unresponsive:
+    // Reset temporary touch state to ensure we release unnecessary references to input channels.
+    mTempTouchState.reset();
+
     nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
     updateDispatchStatisticsLocked(currentTime, entry,
             injectionResult, timeSpentWaitingForApplication);
@@ -2589,10 +2592,14 @@
         AutoMutex _l(mLock);
 
         if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
-            if (mDispatchFrozen && ! frozen) {
+            if (mDispatchFrozen && !frozen) {
                 resetANRTimeoutsLocked();
             }
 
+            if (mDispatchEnabled && !enabled) {
+                resetAndDropEverythingLocked("dispatcher is being disabled");
+            }
+
             mDispatchEnabled = enabled;
             mDispatchFrozen = frozen;
             changed = true;
@@ -2687,6 +2694,21 @@
     return true;
 }
 
+void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
+#if DEBUG_FOCUS
+    LOGD("Resetting and dropping all events (%s).", reason);
+#endif
+
+    synthesizeCancelationEventsForAllConnectionsLocked(InputState::CANCEL_ALL_EVENTS, reason);
+
+    resetKeyRepeatLocked();
+    releasePendingEventLocked();
+    drainInboundQueueLocked();
+    resetTargetsLocked();
+
+    mTouchState.reset();
+}
+
 void InputDispatcher::logDispatchStateLocked() {
     String8 dump;
     dumpDispatchStateLocked(dump);
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 66a93f04..381b77a 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -229,6 +229,12 @@
         return sFileTypeMap.get(path.substring(lastDot + 1).toUpperCase());
     }
 
+    public static boolean isMimeTypeMedia(String mimeType) {
+        int fileType = getFileTypeForMimeType(mimeType);
+        return isAudioFileType(fileType) || isVideoFileType(fileType)
+                || isImageFileType(fileType) || isPlayListFileType(fileType);
+    }
+
     // generates a title based on file name
     public static String getFileTitle(String path) {
         // extract file name after last slash
diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java
index 6303b9d..573208a 100755
--- a/media/java/android/media/videoeditor/AudioTrack.java
+++ b/media/java/android/media/videoeditor/AudioTrack.java
@@ -48,6 +48,8 @@
 

     // The audio waveform filename

     private String mAudioWaveformFilename;

+    // The audio waveform data

+    private WaveformData mWaveformData;

 

     /**

      * An object of this type cannot be instantiated by using the default

@@ -103,6 +105,7 @@
 

         // The audio waveform file is generated later

         mAudioWaveformFilename = null;

+        mWaveformData = null;

     }

 

     /**

@@ -161,6 +164,11 @@
         mDuckedTrackVolume = duckedTrackVolume;

 

         mAudioWaveformFilename = audioWaveformFilename;

+        if (audioWaveformFilename != null) {

+            mWaveformData = new WaveformData(audioWaveformFilename);

+        } else {

+            mWaveformData = null;

+        }

     }

 

     /**

@@ -416,6 +424,7 @@
             throws IOException {

         // TODO: Set mAudioWaveformFilename at the end once the extract is

         // complete

+        mWaveformData = new WaveformData(mAudioWaveformFilename);

     }

 

     /**

@@ -431,10 +440,17 @@
      *

      * @return the name of the file, null if the file does not exist

      */

-    public String getAudioWaveformFilename() {

+    String getAudioWaveformFilename() {

         return mAudioWaveformFilename;

     }

 

+    /**

+     * @return The waveform data

+     */

+    public WaveformData getWaveformData() {

+        return mWaveformData;

+    }

+

     /*

      * {@inheritDoc}

      */

diff --git a/media/java/android/media/videoeditor/Effect.java b/media/java/android/media/videoeditor/Effect.java
index f5e6a67..8547e13 100755
--- a/media/java/android/media/videoeditor/Effect.java
+++ b/media/java/android/media/videoeditor/Effect.java
@@ -57,7 +57,7 @@
             throw new IllegalArgumentException("Media item cannot be null");

         }

 

-        if (startTimeMs + durationMs > mediaItem.getTimelineDuration()) {

+        if (startTimeMs + durationMs > mediaItem.getDuration()) {

             throw new IllegalArgumentException("Invalid start time and duration");

         }

 

@@ -81,7 +81,7 @@
      * @param durationMs of the effect in milliseconds

      */

     public void setDuration(long durationMs) {

-        if (mStartTimeMs + durationMs > mMediaItem.getTimelineDuration()) {

+        if (mStartTimeMs + durationMs > mMediaItem.getDuration()) {

             throw new IllegalArgumentException("Duration is too large");

         }

 

@@ -107,7 +107,7 @@
      *            of the media item in milliseconds

      */

     public void setStartTime(long startTimeMs) {

-        if (startTimeMs + mDurationMs > mMediaItem.getTimelineDuration()) {

+        if (startTimeMs + mDurationMs > mMediaItem.getDuration()) {

             throw new IllegalArgumentException("Start time is too large");

         }

 

@@ -130,7 +130,7 @@
      * @param durationMs The duration in milliseconds

      */

     public void setStartTimeAndDuration(long startTimeMs, long durationMs) {

-        if (startTimeMs + durationMs > mMediaItem.getTimelineDuration()) {

+        if (startTimeMs + durationMs > mMediaItem.getDuration()) {

             throw new IllegalArgumentException("Invalid start time or duration");

         }

 

diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index d2f3694..6dc36c2 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -172,6 +172,14 @@
      * {@inheritDoc}

      */

     @Override

+    public long getDuration() {

+        return mDurationMs;

+    }

+

+    /*

+     * {@inheritDoc}

+     */

+    @Override

     public long getTimelineDuration() {

         return mDurationMs;

     }

diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java
index 40d3619..04878f7 100755
--- a/media/java/android/media/videoeditor/MediaItem.java
+++ b/media/java/android/media/videoeditor/MediaItem.java
@@ -174,6 +174,11 @@
     public abstract long getTimelineDuration();

 

     /**

+     * @return The is the full duration of the media item (not trimmed)

+     */

+    public abstract long getDuration();

+

+    /**

      * @return The source file type

      */

     public abstract int getFileType();

@@ -223,7 +228,7 @@
             throw new IllegalArgumentException("Effect already exists: " + effect.getId());

         }

 

-        if (effect.getStartTime() + effect.getDuration() > getTimelineDuration()) {

+        if (effect.getStartTime() + effect.getDuration() > getDuration()) {

             throw new IllegalArgumentException(

                     "Effect start time + effect duration > media clip duration");

         }

@@ -300,7 +305,7 @@
             throw new IllegalArgumentException("Overlay already exists: " + overlay.getId());

         }

 

-        if (overlay.getStartTime() + overlay.getDuration() > getTimelineDuration()) {

+        if (overlay.getStartTime() + overlay.getDuration() > getDuration()) {

             throw new IllegalArgumentException(

                     "Overlay start time + overlay duration > media clip duration");

         }

@@ -455,7 +460,7 @@
         }

 

         if (mEndTransition != null) {

-            if (effect.getStartTime() + effect.getDuration() > getTimelineDuration()

+            if (effect.getStartTime() + effect.getDuration() > getDuration()

                     - mEndTransition.getDuration()) {

                 mEndTransition.invalidate();

             }

@@ -476,7 +481,7 @@
         }

 

         if (mEndTransition != null) {

-            if (overlay.getStartTime() + overlay.getDuration() > getTimelineDuration()

+            if (overlay.getStartTime() + overlay.getDuration() > getDuration()

                     - mEndTransition.getDuration()) {

                 mEndTransition.invalidate();

             }

@@ -511,7 +516,7 @@
         for (Effect effect : effects) {

             // Adjust the start time if necessary

             final long effectStartTimeMs;

-            if (effect.getStartTime() > getTimelineDuration()) {

+            if (effect.getStartTime() > getDuration()) {

                 effectStartTimeMs = 0;

             } else {

                 effectStartTimeMs = effect.getStartTime();

@@ -519,8 +524,8 @@
 

             // Adjust the duration if necessary

             final long effectDurationMs;

-            if (effectStartTimeMs + effect.getDuration() > getTimelineDuration()) {

-                effectDurationMs = getTimelineDuration() - effectStartTimeMs;

+            if (effectStartTimeMs + effect.getDuration() > getDuration()) {

+                effectDurationMs = getDuration() - effectStartTimeMs;

             } else {

                 effectDurationMs = effect.getDuration();

             }

@@ -540,7 +545,7 @@
         for (Overlay overlay : overlays) {

             // Adjust the start time if necessary

             final long overlayStartTimeMs;

-            if (overlay.getStartTime() > getTimelineDuration()) {

+            if (overlay.getStartTime() > getDuration()) {

                 overlayStartTimeMs = 0;

             } else {

                 overlayStartTimeMs = overlay.getStartTime();

@@ -548,8 +553,8 @@
 

             // Adjust the duration if necessary

             final long overlayDurationMs;

-            if (overlayStartTimeMs + overlay.getDuration() > getTimelineDuration()) {

-                overlayDurationMs = getTimelineDuration() - overlayStartTimeMs;

+            if (overlayStartTimeMs + overlay.getDuration() > getDuration()) {

+                overlayDurationMs = getDuration() - overlayStartTimeMs;

             } else {

                 overlayDurationMs = overlay.getDuration();

             }

diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index 341bf8e..1fa98e7 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -46,6 +46,8 @@
     private int mVolumePercentage;

     private boolean mMuted;

     private String mAudioWaveformFilename;

+    // The audio waveform data

+    private WaveformData mWaveformData;

 

     /**

      * An object of this type cannot be instantiated with a default constructor

@@ -115,6 +117,11 @@
         mVolumePercentage = volumePercent;

         mMuted = muted;

         mAudioWaveformFilename = audioWaveformFilename;

+        if (audioWaveformFilename != null) {

+            mWaveformData = new WaveformData(audioWaveformFilename);

+        } else {

+            mWaveformData = null;

+        }

     }

 

     /**

@@ -236,16 +243,16 @@
         return mHeight;

     }

 

-    /**

-     * @return The duration of the video clip

+    /*

+     * {@inheritDoc}

      */

+    @Override

     public long getDuration() {

         return mDurationMs;

     }

 

-    /**

-     * @return The timeline duration. This is the actual duration in the

-     *      timeline (trimmed duration)

+    /*

+     * {@inheritDoc}

      */

     @Override

     public long getTimelineDuration() {

@@ -286,6 +293,7 @@
     public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener)

             throws IOException {

         // TODO: Set mAudioWaveformFilename at the end once the export is complete

+        mWaveformData = new WaveformData(mAudioWaveformFilename);

     }

 

     /**

@@ -299,11 +307,18 @@
      * @return the name of the file, null if the file has not been computed or

      *         if there is no Audio track in the mediaItem

      */

-    public String getAudioWaveformFilename() {

+    String getAudioWaveformFilename() {

         return mAudioWaveformFilename;

     }

 

     /**

+     * @return The waveform data

+     */

+    public WaveformData getWaveformData() {

+        return mWaveformData;

+    }

+

+    /**

      * Set volume of the Audio track of this mediaItem

      *

      * @param volumePercent in %/. 100% means no change; 50% means half value, 200%

diff --git a/media/java/android/media/videoeditor/Overlay.java b/media/java/android/media/videoeditor/Overlay.java
index c58b5cb..fff9ca2 100755
--- a/media/java/android/media/videoeditor/Overlay.java
+++ b/media/java/android/media/videoeditor/Overlay.java
@@ -60,7 +60,7 @@
             throw new IllegalArgumentException("Media item cannot be null");

         }

 

-        if (startTimeMs + durationMs > mediaItem.getTimelineDuration()) {

+        if (startTimeMs + durationMs > mediaItem.getDuration()) {

             throw new IllegalArgumentException("Invalid start time and duration");

         }

 

@@ -92,7 +92,7 @@
      * @param durationMs The duration in milliseconds

      */

     public void setDuration(long durationMs) {

-        if (mStartTimeMs + durationMs > mMediaItem.getTimelineDuration()) {

+        if (mStartTimeMs + durationMs > mMediaItem.getDuration()) {

             throw new IllegalArgumentException("Duration is too large");

         }

 

@@ -116,7 +116,7 @@
      * @param startTimeMs start time in milliseconds

      */

     public void setStartTime(long startTimeMs) {

-        if (startTimeMs + mDurationMs > mMediaItem.getTimelineDuration()) {

+        if (startTimeMs + mDurationMs > mMediaItem.getDuration()) {

             throw new IllegalArgumentException("Start time is too large");

         }

 

@@ -132,7 +132,7 @@
      * @param durationMs The duration in milliseconds

      */

     public void setStartTimeAndDuration(long startTimeMs, long durationMs) {

-        if (startTimeMs + durationMs > mMediaItem.getTimelineDuration()) {

+        if (startTimeMs + durationMs > mMediaItem.getDuration()) {

             throw new IllegalArgumentException("Invalid start time or duration");

         }

 

diff --git a/media/java/android/media/videoeditor/TransitionEndCurtainClosing.java b/media/java/android/media/videoeditor/TransitionEndCurtainClosing.java
deleted file mode 100644
index b1c6bb5..0000000
--- a/media/java/android/media/videoeditor/TransitionEndCurtainClosing.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*

- * Copyright (C) 2010 The Android Open Source Project

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *      http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-package android.media.videoeditor;

-

-/**

- * This transition fades to black frame using curtain closing: A black image is

- * moved from top to bottom to cover the video. This transition is always

- * applied at the end of the movie. {@hide}

- */

-public class TransitionEndCurtainClosing extends Transition {

-    /**

-     * An object of this type cannot be instantiated by using the default

-     * constructor

-     */

-    @SuppressWarnings("unused")

-    private TransitionEndCurtainClosing() {

-        this(null, null, 0, BEHAVIOR_LINEAR);

-    }

-

-    /**

-     * Constructor.

-     *

-     * @param transitionId The transition id

-     * @param afterMediaItem The transition is applied to the end of this

-     *      media item

-     * @param durationMs duration of the transition in milliseconds

-     * @param behavior The transition behavior

-     */

-    public TransitionEndCurtainClosing(String transitionId, MediaItem afterMediaItem,

-            long duration, int behavior) {

-        super(transitionId, afterMediaItem, null, duration, behavior);

-    }

-

-    /*

-     * {@inheritDoc}

-     */

-    @Override

-    void generate() {

-    }

-}

diff --git a/media/java/android/media/videoeditor/TransitionEndFadeToBlack.java b/media/java/android/media/videoeditor/TransitionEndFadeToBlack.java
deleted file mode 100755
index 5f913fc..0000000
--- a/media/java/android/media/videoeditor/TransitionEndFadeToBlack.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*

- * Copyright (C) 2010 The Android Open Source Project

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *      http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-package android.media.videoeditor;

-

-/**

- * This transition fades to black frame using fade out in a certain provided

- * duration. This transition is always applied at the end of the movie. {@hide

- * }

- */

-public class TransitionEndFadeToBlack extends Transition {

-    /**

-     * An object of this type cannot be instantiated by using the default

-     * constructor

-     */

-    @SuppressWarnings("unused")

-    private TransitionEndFadeToBlack() {

-        this(null, null, 0, BEHAVIOR_LINEAR);

-    }

-

-    /**

-     * Constructor.

-     *

-     * @param transitionId The transition id

-     * @param afterMediaItem The transition is applied to the end of this

-     *      media item

-     * @param durationMs duration of the transition in milliseconds

-     * @param behavior The transition behavior

-     */

-    public TransitionEndFadeToBlack(String transitionId, MediaItem afterMediaItem, long duration,

-            int behavior) {

-        super(transitionId, afterMediaItem, null, duration, behavior);

-    }

-

-    /*

-     * {@inheritDoc}

-     */

-    @Override

-    void generate() {

-    }

-}

diff --git a/media/java/android/media/videoeditor/TransitionFadeToBlack.java b/media/java/android/media/videoeditor/TransitionFadeBlack.java
similarity index 85%
rename from media/java/android/media/videoeditor/TransitionFadeToBlack.java
rename to media/java/android/media/videoeditor/TransitionFadeBlack.java
index 9569a65..a9bf4ce 100755
--- a/media/java/android/media/videoeditor/TransitionFadeToBlack.java
+++ b/media/java/android/media/videoeditor/TransitionFadeBlack.java
@@ -18,16 +18,17 @@
 

 

 /**

- * This class is used to render a fade to black transition between two videos.

+ * This class is used to render a fade to black and fade from black transition

+ * between two media items.

  * {@hide}

  */

-public class TransitionFadeToBlack extends Transition {

+public class TransitionFadeBlack extends Transition {

     /**

      * An object of this type cannot be instantiated by using the default

      * constructor

      */

     @SuppressWarnings("unused")

-    private TransitionFadeToBlack() {

+    private TransitionFadeBlack() {

         this(null, null, null, 0, 0);

     }

 

@@ -45,7 +46,7 @@
      *

      * @throws IllegalArgumentException if behavior is not supported.

      */

-    public TransitionFadeToBlack(String transitionId, MediaItem afterMediaItem,

+    public TransitionFadeBlack(String transitionId, MediaItem afterMediaItem,

             MediaItem beforeMediaItem, long durationMs, int behavior) {

         super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);

     }

diff --git a/media/java/android/media/videoeditor/TransitionStartCurtainOpening.java b/media/java/android/media/videoeditor/TransitionStartCurtainOpening.java
deleted file mode 100755
index b787b32..0000000
--- a/media/java/android/media/videoeditor/TransitionStartCurtainOpening.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*

- * Copyright (C) 2010 The Android Open Source Project

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *      http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-package android.media.videoeditor;

-

-

-/**

- * This transition fades from black frame using curtain opening. A black

- * image is displayed and moves from bottom to top making the video visible.

- * This transition is always applied at the beginning of the movie.

- * {@hide}

- */

-public class TransitionStartCurtainOpening extends Transition {

-    /**

-     * An object of this type cannot be instantiated by using the default

-     * constructor

-     */

-    @SuppressWarnings("unused")

-    private TransitionStartCurtainOpening() {

-        this(null, null, 0, Transition.BEHAVIOR_LINEAR);

-    }

-

-    /**

-     * Constructor

-     *

-     * @param transitionId The transition id

-     * @param beforeMediaItem The transition is applied to the beginning of

-     *      this media item

-     * @param durationMs The duration of the transition in milliseconds

-     * @param behavior The transition behavior

-     */

-    public TransitionStartCurtainOpening(String transitionId, MediaItem beforeMediaItem,

-            long durationMs, int behavior) {

-        super(transitionId, null, beforeMediaItem, durationMs, behavior);

-    }

-

-    /*

-     * {@inheritDoc}

-     */

-    @Override

-    public void generate() {

-    }

-}

diff --git a/media/java/android/media/videoeditor/TransitionStartFadeFromBlack.java b/media/java/android/media/videoeditor/TransitionStartFadeFromBlack.java
deleted file mode 100644
index be993a5..0000000
--- a/media/java/android/media/videoeditor/TransitionStartFadeFromBlack.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*

- * Copyright (C) 2010 The Android Open Source Project

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *      http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-package android.media.videoeditor;

-

-/**

- * This transition fades from black using fade-in in a certain provided

- * duration. This transition is always applied at the beginning of the movie.

- * {@hide}

- */

-public class TransitionStartFadeFromBlack extends Transition {

-    /**

-     * An object of this type cannot be instantiated by using the default

-     * constructor

-     */

-    @SuppressWarnings("unused")

-    private TransitionStartFadeFromBlack() {

-        this(null, null, 0, Transition.BEHAVIOR_LINEAR);

-    }

-

-    /**

-     * Constructor

-     *

-     * @param transitionId The transition id

-     * @param beforeMediaItem The transition is applied to the beginning of

-     *      this media item

-     * @param durationMs The duration of the transition in milliseconds

-     * @param behavior The transition behavior

-     */

-    public TransitionStartFadeFromBlack(String transitionId, MediaItem beforeMediaItem,

-            long durationMs, int behavior) {

-        super(transitionId, null, beforeMediaItem, durationMs, behavior);

-    }

-

-    /*

-     * {@inheritDoc}

-     */

-    @Override

-    public void generate() {

-    }

-}

diff --git a/media/java/android/media/videoeditor/VideoEditorTestImpl.java b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
index 505b93e..ba84f49 100644
--- a/media/java/android/media/videoeditor/VideoEditorTestImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
@@ -892,13 +892,7 @@
         }
 
         final Transition transition;
-        if (TransitionStartCurtainOpening.class.getSimpleName().equals(type)) {
-            transition = new TransitionStartCurtainOpening(transitionId, beforeMediaItem,
-                    durationMs, behavior);
-        } else if (TransitionStartFadeFromBlack.class.getSimpleName().equals(type)) {
-            transition = new TransitionStartFadeFromBlack(transitionId, beforeMediaItem,
-                    durationMs, behavior);
-        } else if (TransitionAlpha.class.getSimpleName().equals(type)) {
+        if (TransitionAlpha.class.getSimpleName().equals(type)) {
             final int blending = Integer.parseInt(parser.getAttributeValue("", ATTR_BLENDING));
             final String maskFilename = parser.getAttributeValue("", ATTR_MASK);
             final boolean invert = Boolean.getBoolean(parser.getAttributeValue("", ATTR_INVERT));
@@ -911,15 +905,9 @@
             final int direction = Integer.parseInt(parser.getAttributeValue("", ATTR_DIRECTION));
             transition = new TransitionSliding(transitionId, afterMediaItem, beforeMediaItem,
                     durationMs, behavior, direction);
-        } else if (TransitionFadeToBlack.class.getSimpleName().equals(type)) {
-            transition = new TransitionFadeToBlack(transitionId, afterMediaItem, beforeMediaItem,
+        } else if (TransitionFadeBlack.class.getSimpleName().equals(type)) {
+            transition = new TransitionFadeBlack(transitionId, afterMediaItem, beforeMediaItem,
                     durationMs, behavior);
-        } else if (TransitionEndCurtainClosing.class.getSimpleName().equals(type)) {
-            transition = new TransitionEndCurtainClosing(transitionId, afterMediaItem, durationMs,
-                    behavior);
-        } else if (TransitionEndFadeToBlack.class.getSimpleName().equals(type)) {
-            transition = new TransitionEndFadeToBlack(transitionId, afterMediaItem, durationMs,
-                    behavior);
         } else {
             transition = null;
         }
@@ -1132,17 +1120,14 @@
      */
     private void computeTimelineDuration() {
         mDurationMs = 0;
-        for (MediaItem mediaItem : mMediaItems) {
+        final int mediaItemsCount = mMediaItems.size();
+        for (int i = 0; i < mediaItemsCount; i++) {
+            final MediaItem mediaItem = mMediaItems.get(i);
             mDurationMs += mediaItem.getTimelineDuration();
-        }
-
-        // Subtract the transition times
-        for (Transition transition : mTransitions) {
-            if (!(transition instanceof TransitionStartCurtainOpening)
-                    && !(transition instanceof TransitionStartFadeFromBlack)
-                    && !(transition instanceof TransitionEndFadeToBlack)
-                    && !(transition instanceof TransitionEndCurtainClosing)) {
-                mDurationMs -= transition.getDuration();
+            if (mediaItem.getEndTransition() != null) {
+                if (i < mediaItemsCount - 1) {
+                    mDurationMs -= mediaItem.getEndTransition().getDuration();
+                }
             }
         }
     }
diff --git a/media/java/android/media/videoeditor/WaveformData.java b/media/java/android/media/videoeditor/WaveformData.java
new file mode 100644
index 0000000..b53bd7d
--- /dev/null
+++ b/media/java/android/media/videoeditor/WaveformData.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.videoeditor;
+
+/**
+ * Class which describes the waveform data of an audio track. The gain values
+ * represent the average gain for an audio frame. For audio codecs which do
+ * not operate on a per frame bases (eg. ALAW, ULAW) a reasonable audio frame
+ * duration will be assumed (eg. 50ms).
+ * {@hide}
+ */
+public class WaveformData {
+    // Instance variables
+    private final int mFrameDurationMs;
+    private final int mFramesCount;
+    private final short[] mGains;
+
+    /**
+     * This constructor shall not be used
+     */
+    @SuppressWarnings("unused")
+    private WaveformData() {
+        mFrameDurationMs = 0;
+        mFramesCount = 0;
+        mGains = null;
+    }
+
+    /**
+     * Constructor
+     *
+     * @param audioWaveformFilename The name of the audio waveform file
+     */
+    WaveformData(String audioWaveformFilename) {
+        // TODO: Read these values from the file
+        mFrameDurationMs = 20;
+        mFramesCount = 300000 / mFrameDurationMs;
+        mGains = new short[mFramesCount];
+        for (int i = 0; i < mFramesCount; i++) {
+            mGains[i] = (short)((i * 5) % 256);
+        }
+    }
+
+    /**
+     * @return The duration of a frame in milliseconds
+     */
+    public int getFrameDuration() {
+        return mFrameDurationMs;
+    }
+
+    /**
+     * @return The number of frames within the waveform data
+     */
+    public int getFramesCount() {
+        return mFramesCount;
+    }
+
+    /**
+     * @return The array of frame gains. The size of the array is the frames
+     *  count. The values of the frame gains range from 0 to 256.
+     */
+    public short[] getFrameGains() {
+        return mGains;
+    }
+}
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 5505f14..c957dba 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -243,19 +243,22 @@
     // derive capture scaling factor from peak value in current buffer
     // this gives more interesting captures for display.
     int32_t shift = 32;
-    for (size_t i = 0; i < inBuffer->frameCount; i++) {
+    int len = inBuffer->frameCount * 2;
+    for (size_t i = 0; i < len; i++) {
         int32_t smp = inBuffer->s16[i];
-        if (smp < 0) smp = -smp;
+        if (smp < 0) smp = -smp - 1; // take care to keep the max negative in range
         int32_t clz = __builtin_clz(smp);
         if (shift > clz) shift = clz;
     }
-    // never scale by less than 8 to avoid returning unaltered PCM signal.
-    // add one to combine the division by 2 needed after summing left and right channels below
-    if (20 > shift) {
-        shift = (31 - 8 + 1) - shift;
-    } else {
-        shift = (3 + 1);
+    // A maximum amplitude signal will have 17 leading zeros, which we want to
+    // translate to a shift of 8 (for converting 16 bit to 8 bit)
+     shift = 25 - shift;
+    // Never scale by less than 8 to avoid returning unaltered PCM signal.
+    if (shift < 3) {
+        shift = 3;
     }
+    // add one to combine the division by 2 needed after summing left and right channels below
+    shift++;
 
     uint32_t captIdx;
     uint32_t inIdx;
@@ -264,7 +267,7 @@
          inIdx < inBuffer->frameCount && captIdx < pContext->mCaptureSize;
          inIdx++, captIdx++) {
         int32_t smp = inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1];
-        smp = (smp + (1 << (shift - 1))) >> shift;
+        smp = smp >> shift;
         buf[captIdx] = ((uint8_t)smp)^0x80;
     }
     pContext->mCaptureIdx = captIdx;
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index b46d8d0..e4f9a47 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -21,7 +21,7 @@
 
 FileSource::FileSource(const char *filename)
     : mFile(fopen(filename, "rb")),
-      mFd(fileno(mFile)),
+      mFd(mFile == NULL ? -1 : fileno(mFile)),
       mOffset(0),
       mLength(-1),
       mDecryptHandle(NULL),
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index ee03c52..965c370 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -65,7 +65,7 @@
     }
 
     if (!strncmp(mime, "drm", 3)) {
-        char *originalMime = strrchr(mime, '+') + 1;
+        const char *originalMime = strrchr(mime, '+') + 1;
 
         if (!strncmp(mime, "drm+es_based", 12)) {
             return new DRMExtractor(source, originalMime);
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 27faf4f..092c33e 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -281,7 +281,7 @@
     mNumSyncSamples = U32_AT(&header[4]);
 
     if (mNumSyncSamples < 2) {
-        LOGW("Table of sync samples is empty or has only a single entry!");
+        LOGV("Table of sync samples is empty or has only a single entry!");
     }
 
     mSyncSamples = new uint32_t[mNumSyncSamples];
diff --git a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
index 52a391f..a6b179e 100644
--- a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
@@ -33,6 +33,80 @@
 
 namespace android {
 
+static status_t ConvertOmxAvcProfileToAvcSpecProfile(
+        int32_t omxProfile, AVCProfile* pvProfile) {
+    LOGV("ConvertOmxAvcProfileToAvcSpecProfile: %d", omxProfile);
+    switch (omxProfile) {
+        case OMX_VIDEO_AVCProfileBaseline:
+            *pvProfile = AVC_BASELINE;
+            return OK;
+        default:
+            LOGE("Unsupported omx profile: %d", omxProfile);
+    }
+    return BAD_VALUE;
+}
+
+static status_t ConvertOmxAvcLevelToAvcSpecLevel(
+        int32_t omxLevel, AVCLevel *pvLevel) {
+    LOGV("ConvertOmxAvcLevelToAvcSpecLevel: %d", omxLevel);
+    AVCLevel level = AVC_LEVEL5_1;
+    switch (omxLevel) {
+        case OMX_VIDEO_AVCLevel1:
+            level = AVC_LEVEL1_B;
+            break;
+        case OMX_VIDEO_AVCLevel1b:
+            level = AVC_LEVEL1;
+            break;
+        case OMX_VIDEO_AVCLevel11:
+            level = AVC_LEVEL1_1;
+            break;
+        case OMX_VIDEO_AVCLevel12:
+            level = AVC_LEVEL1_2;
+            break;
+        case OMX_VIDEO_AVCLevel13:
+            level = AVC_LEVEL1_3;
+            break;
+        case OMX_VIDEO_AVCLevel2:
+            level = AVC_LEVEL2;
+            break;
+        case OMX_VIDEO_AVCLevel21:
+            level = AVC_LEVEL2_1;
+            break;
+        case OMX_VIDEO_AVCLevel22:
+            level = AVC_LEVEL2_2;
+            break;
+        case OMX_VIDEO_AVCLevel3:
+            level = AVC_LEVEL3;
+            break;
+        case OMX_VIDEO_AVCLevel31:
+            level = AVC_LEVEL3_1;
+            break;
+        case OMX_VIDEO_AVCLevel32:
+            level = AVC_LEVEL3_2;
+            break;
+        case OMX_VIDEO_AVCLevel4:
+            level = AVC_LEVEL4;
+            break;
+        case OMX_VIDEO_AVCLevel41:
+            level = AVC_LEVEL4_1;
+            break;
+        case OMX_VIDEO_AVCLevel42:
+            level = AVC_LEVEL4_2;
+            break;
+        case OMX_VIDEO_AVCLevel5:
+            level = AVC_LEVEL5;
+            break;
+        case OMX_VIDEO_AVCLevel51:
+            level = AVC_LEVEL5_1;
+            break;
+        default:
+            LOGE("Unknown omx level: %d", omxLevel);
+            return BAD_VALUE;
+    }
+    *pvLevel = level;
+    return OK;
+}
+
 inline static void ConvertYUV420SemiPlanarToYUV420Planar(
         uint8_t *inyuv, uint8_t* outyuv,
         int32_t width, int32_t height) {
@@ -231,10 +305,16 @@
     mEncParams->level = AVC_LEVEL3_2;
     int32_t profile, level;
     if (meta->findInt32(kKeyVideoProfile, &profile)) {
-        mEncParams->profile = (AVCProfile) profile;
+        if (OK != ConvertOmxAvcProfileToAvcSpecProfile(
+                        profile, &mEncParams->profile)) {
+            return BAD_VALUE;
+        }
     }
     if (meta->findInt32(kKeyVideoLevel, &level)) {
-        mEncParams->level = (AVCLevel) level;
+        if (OK != ConvertOmxAvcLevelToAvcSpecLevel(
+                        level, &mEncParams->level)) {
+            return BAD_VALUE;
+        }
     }
 
 
diff --git a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
index a011137..d5a5313 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
@@ -32,6 +32,104 @@
 
 namespace android {
 
+static status_t ConvertOmxProfileLevel(
+        MP4EncodingMode mode,
+        int32_t omxProfile,
+        int32_t omxLevel,
+        ProfileLevelType* pvProfileLevel) {
+    LOGV("ConvertOmxProfileLevel: %d/%d/%d", mode, omxProfile, omxLevel);
+    ProfileLevelType profileLevel;
+    if (mode == H263_MODE) {
+        switch (omxProfile) {
+            case OMX_VIDEO_H263ProfileBaseline:
+                if (omxLevel > OMX_VIDEO_H263Level45) {
+                    LOGE("Unsupported level (%d) for H263", omxLevel);
+                    return BAD_VALUE;
+                } else {
+                    LOGW("PV does not support level configuration for H263");
+                    profileLevel = CORE_PROFILE_LEVEL2;
+                    break;
+                }
+            default:
+                LOGE("Unsupported profile (%d) for H263", omxProfile);
+                return BAD_VALUE;
+        }
+    } else {  // MPEG4
+        switch (omxProfile) {
+            case OMX_VIDEO_MPEG4ProfileSimple:
+                switch (omxLevel) {
+                    case OMX_VIDEO_MPEG4Level0b:
+                        profileLevel = SIMPLE_PROFILE_LEVEL0;
+                        break;
+                    case OMX_VIDEO_MPEG4Level1:
+                        profileLevel = SIMPLE_PROFILE_LEVEL1;
+                        break;
+                    case OMX_VIDEO_MPEG4Level2:
+                        profileLevel = SIMPLE_PROFILE_LEVEL2;
+                        break;
+                    case OMX_VIDEO_MPEG4Level3:
+                        profileLevel = SIMPLE_PROFILE_LEVEL3;
+                        break;
+                    default:
+                        LOGE("Unsupported level (%d) for MPEG4 simple profile",
+                            omxLevel);
+                        return BAD_VALUE;
+            }
+            case OMX_VIDEO_MPEG4ProfileSimpleScalable:
+                switch (omxLevel) {
+                    case OMX_VIDEO_MPEG4Level0b:
+                        profileLevel = SIMPLE_SCALABLE_PROFILE_LEVEL0;
+                        break;
+                    case OMX_VIDEO_MPEG4Level1:
+                        profileLevel = SIMPLE_SCALABLE_PROFILE_LEVEL1;
+                        break;
+                    case OMX_VIDEO_MPEG4Level2:
+                        profileLevel = SIMPLE_SCALABLE_PROFILE_LEVEL2;
+                        break;
+                    default:
+                        LOGE("Unsupported level (%d) for MPEG4 simple "
+                             "scalable profile", omxLevel);
+                        return BAD_VALUE;
+                }
+            case OMX_VIDEO_MPEG4ProfileCore:
+                switch (omxLevel) {
+                    case OMX_VIDEO_MPEG4Level1:
+                        profileLevel = CORE_PROFILE_LEVEL1;
+                        break;
+                    case OMX_VIDEO_MPEG4Level2:
+                        profileLevel = CORE_PROFILE_LEVEL2;
+                        break;
+                    default:
+                        LOGE("Unsupported level (%d) for MPEG4 core "
+                             "profile", omxLevel);
+                        return BAD_VALUE;
+                }
+            case OMX_VIDEO_MPEG4ProfileCoreScalable:
+                switch (omxLevel) {
+                    case OMX_VIDEO_MPEG4Level1:
+                        profileLevel = CORE_SCALABLE_PROFILE_LEVEL1;
+                        break;
+                    case OMX_VIDEO_MPEG4Level2:
+                        profileLevel = CORE_SCALABLE_PROFILE_LEVEL2;
+                        break;
+                    case OMX_VIDEO_MPEG4Level3:
+                        profileLevel = CORE_SCALABLE_PROFILE_LEVEL3;
+                        break;
+                    default:
+                        LOGE("Unsupported level (%d) for MPEG4 core "
+                             "scalable profile", omxLevel);
+                        return BAD_VALUE;
+                }
+            default:
+                LOGE("Unsupported MPEG4 profile (%d)", omxProfile);
+                return BAD_VALUE;
+        }
+    }
+
+    *pvProfileLevel = profileLevel;
+    return OK;
+}
+
 inline static void ConvertYUV420SemiPlanarToYUV420Planar(
         uint8_t *inyuv, uint8_t* outyuv,
         int32_t width, int32_t height) {
@@ -150,9 +248,14 @@
     // If profile and level setting is not correct, failure
     // is reported when the encoder is initialized.
     mEncParams->profile_level = CORE_PROFILE_LEVEL2;
-    int32_t profileLevel;
-    if (meta->findInt32(kKeyVideoLevel, &profileLevel)) {
-        mEncParams->profile_level = (ProfileLevelType)profileLevel;
+    int32_t profile, level;
+    if (meta->findInt32(kKeyVideoProfile, &profile) &&
+        meta->findInt32(kKeyVideoLevel, &level)) {
+        if (OK != ConvertOmxProfileLevel(
+                        mEncParams->encMode, profile, level,
+                        &mEncParams->profile_level)) {
+            return BAD_VALUE;
+        }
     }
 
     mEncParams->packetSize = 32;
diff --git a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
index 703b41e..e14fb95 100644
--- a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
@@ -112,7 +112,12 @@
 
     mAnchorTimeUs = 0;
     mNumFramesOutput = 0;
-    mNumFramesLeftOnPage = 0;
+
+    // If the source never limits the number of valid frames contained
+    // in the input data, we'll assume that all of the decoded frames are
+    // valid.
+    mNumFramesLeftOnPage = -1;
+
     mStarted = true;
 
     return OK;
@@ -193,12 +198,14 @@
         }
     }
 
-    if (numFrames > mNumFramesLeftOnPage) {
-        LOGV("discarding %d frames at end of page",
-             numFrames - mNumFramesLeftOnPage);
-        numFrames = mNumFramesLeftOnPage;
+    if (mNumFramesLeftOnPage >= 0) {
+        if (numFrames > mNumFramesLeftOnPage) {
+            LOGV("discarding %d frames at end of page",
+                 numFrames - mNumFramesLeftOnPage);
+            numFrames = mNumFramesLeftOnPage;
+        }
+        mNumFramesLeftOnPage -= numFrames;
     }
-    mNumFramesLeftOnPage -= numFrames;
 
     out->set_range(0, numFrames * sizeof(int16_t) * mNumChannels);
 
@@ -241,6 +248,7 @@
     int32_t numPageSamples;
     if (inputBuffer->meta_data()->findInt32(
                 kKeyValidSamples, &numPageSamples)) {
+        CHECK(numPageSamples >= 0);
         mNumFramesLeftOnPage = numPageSamples;
     }
 
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 7c7d69e..d16476d 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -252,7 +252,7 @@
 }
 
 void BlockIterator::seek(int64_t seekTimeUs) {
-    mCluster = mSegment->GetCluster(seekTimeUs * 1000ll);
+    mCluster = mSegment->FindCluster(seekTimeUs * 1000ll);
     mBlockEntry = mCluster != NULL ? mCluster->GetFirst() : NULL;
 
     while (!eos() && block()->GetTrackNumber() != mTrackNum) {
@@ -476,7 +476,7 @@
 
         size_t codecPrivateSize;
         const unsigned char *codecPrivate =
-            track->GetCodecPrivate(&codecPrivateSize);
+            track->GetCodecPrivate(codecPrivateSize);
 
         enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
 
diff --git a/media/libstagefright/matroska/mkvparser.cpp b/media/libstagefright/matroska/mkvparser.cpp
index 4e51004..455b1d6 100644
--- a/media/libstagefright/matroska/mkvparser.cpp
+++ b/media/libstagefright/matroska/mkvparser.cpp
@@ -1,3103 +1,4511 @@
-#include "mkvparser.hpp"
-#include <cassert>
-#include <cstring>
-
-mkvparser::IMkvReader::~IMkvReader()
-{
-}
-
-long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    long long total, available;
-
-    long hr = pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(pos < available);
-    assert((available - pos) >= 1);  //assume here max u-int len is 8
-    
-    unsigned char b;
-
-    hr = pReader->Read(pos, 1, &b);
-    if (hr < 0)
-        return hr;
-        
-    assert(hr == 0L);
-    
-    if (b & 0x80)       //1000 0000
-    {
-        len = 1;
-        b &= 0x7F;      //0111 1111
-    }        
-    else if (b & 0x40)  //0100 0000
-    {
-        len = 2;
-        b &= 0x3F;      //0011 1111
-    }
-    else if (b & 0x20)  //0010 0000
-    {
-        len = 3;
-        b &= 0x1F;      //0001 1111
-    }
-    else if (b & 0x10)  //0001 0000
-    {
-        len = 4;
-        b &= 0x0F;      //0000 1111
-    }
-    else if (b & 0x08)  //0000 1000
-    {
-        len = 5;
-        b &= 0x07;      //0000 0111
-    }
-    else if (b & 0x04)  //0000 0100
-    {
-        len = 6;
-        b &= 0x03;      //0000 0011
-    }
-    else if (b & 0x02)  //0000 0010
-    {
-        len = 7;
-        b &= 0x01;      //0000 0001
-    }
-    else 
-    {
-        assert(b & 0x01);  //0000 0001
-        len = 8;
-        b = 0;             //0000 0000
-    }
-    
-    assert((available - pos) >= len);
-    
-    long long result = b;
-    ++pos;
-    for (long i = 1; i < len; ++i)
-    {
-        hr = pReader->Read(pos, 1, &b);
-        
-        if (hr < 0)
-            return hr;
-            
-        assert(hr == 0L);
-        
-        result <<= 8;
-        result |= b;
-        
-        ++pos;
-    }
-    
-    return result;
-}
-    
-    
-long long mkvparser::GetUIntLength(
-    IMkvReader* pReader,
-    long long pos, 
-    long& len)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    long long total, available;
-
-    long hr = pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(available <= total);
-    
-    if (pos >= available)
-        return pos;  //too few bytes available
-    
-    unsigned char b;
-    
-    hr = pReader->Read(pos, 1, &b);
-    
-    if (hr < 0)
-        return hr;
-
-    assert(hr == 0L);
-    
-    if (b == 0)  //we can't handle u-int values larger than 8 bytes
-        return E_FILE_FORMAT_INVALID;
-    
-    unsigned char m = 0x80;
-    len = 1;
-    
-    while (!(b & m))
-    {
-        m >>= 1;
-        ++len;
-    }
-    
-    return 0;  //success
-}
-
-
-long long mkvparser::SyncReadUInt(
-    IMkvReader* pReader,
-    long long pos, 
-    long long stop,
-    long& len)
-{
-    assert(pReader);
-
-    if (pos >= stop)
-        return E_FILE_FORMAT_INVALID;
-    
-    unsigned char b;
-    
-    long hr = pReader->Read(pos, 1, &b);
-    
-    if (hr < 0)
-        return hr;
-        
-    if (hr != 0L)
-        return E_BUFFER_NOT_FULL;
-
-    if (b == 0)  //we can't handle u-int values larger than 8 bytes
-        return E_FILE_FORMAT_INVALID;
-    
-    unsigned char m = 0x80;
-    len = 1;
-        
-    while (!(b & m))
-    {
-        m >>= 1;
-        ++len;
-    }
-    
-    if ((pos + len) > stop)
-        return E_FILE_FORMAT_INVALID;
-        
-    long long result = b & (~m);
-    ++pos;
-    
-    for (int i = 1; i < len; ++i)
-    {
-        hr = pReader->Read(pos, 1, &b);
-        
-        if (hr < 0)
-            return hr;
-           
-        if (hr != 0L)
-            return E_BUFFER_NOT_FULL;
-            
-        result <<= 8;
-        result |= b;
-        
-        ++pos;
-    }
-    
-    return result;
-}
-
-
-long long mkvparser::UnserializeUInt(
-    IMkvReader* pReader, 
-    long long pos,
-    long long size)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    assert(size > 0);
-    assert(size <= 8);
-    
-    long long result = 0;
-    
-    for (long long i = 0; i < size; ++i)
-    {
-        unsigned char b;
-        
-        const long hr = pReader->Read(pos, 1, &b);
-        
-        if (hr < 0)      
-            return hr;
-        result <<= 8;
-        result |= b;
-        
-        ++pos;
-    }
-    
-    return result;
-}
-
-
-float mkvparser::Unserialize4Float(
-    IMkvReader* pReader, 
-    long long pos)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    long long total, available;
-    
-    long hr = pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(available <= total);
-    assert((pos + 4) <= available);
-    
-    float result;
-    
-    unsigned char* const p = (unsigned char*)&result;
-    unsigned char* q = p + 4;
-    
-    for (;;)
-    {
-        hr = pReader->Read(pos, 1, --q);
-        assert(hr == 0L);
-        
-        if (q == p)
-            break;
-            
-        ++pos;
-    }
-    
-    return result;
-}
-
-
-double mkvparser::Unserialize8Double(
-    IMkvReader* pReader, 
-    long long pos)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    double result;
-    
-    unsigned char* const p = (unsigned char*)&result;
-    unsigned char* q = p + 8;
-    
-    for (;;)
-    {
-        const long hr = pReader->Read(pos, 1, --q);
-        assert(hr == 0L);
-        
-        if (q == p)
-            break;
-            
-        ++pos;
-    }
-    
-    return result;
-}
-
-signed char mkvparser::Unserialize1SInt(
-    IMkvReader* pReader,
-    long long pos)
-{
-    assert(pReader);
-    assert(pos >= 0);
- 
-    long long total, available;
-
-    long hr = pReader->Length(&total, &available);
-    assert(hr == 0);   
-    assert(available <= total);
-    assert(pos < available);
-
-    signed char result;
-
-    hr = pReader->Read(pos, 1, (unsigned char*)&result);
-    assert(hr == 0);
-
-    return result;
-}
-
-short mkvparser::Unserialize2SInt(
-    IMkvReader* pReader, 
-    long long pos)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    long long total, available;
-    
-    long hr = pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(available <= total);
-    assert((pos + 2) <= available);
-    
-    short result;
-    
-    unsigned char* const p = (unsigned char*)&result;
-    unsigned char* q = p + 2;
-    
-    for (;;)
-    {
-        hr = pReader->Read(pos, 1, --q);
-        assert(hr == 0L);
-        
-        if (q == p)
-            break;
-            
-        ++pos;
-    }
-    
-    return result;
-}
-
-
-bool mkvparser::Match(
-    IMkvReader* pReader,
-    long long& pos,
-    unsigned long id_,
-    long long& val)
-
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    long long total, available;
-
-    long hr = pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(available <= total);
-    
-    long len;
-
-    const long long id = ReadUInt(pReader, pos, len);
-    assert(id >= 0);
-    assert(len > 0);
-    assert(len <= 8);
-    assert((pos + len) <= available);
-    
-    if ((unsigned long)id != id_)
-        return false;
-        
-    pos += len;  //consume id
-    
-    const long long size = ReadUInt(pReader, pos, len);
-    assert(size >= 0);
-    assert(size <= 8);
-    assert(len > 0);
-    assert(len <= 8);
-    assert((pos + len) <= available);
-    
-    pos += len;  //consume length of size of payload
-    
-    val = UnserializeUInt(pReader, pos, size);
-    assert(val >= 0);
-    
-    pos += size;  //consume size of payload
-    
-    return true;
-}
-
-bool mkvparser::Match(
-    IMkvReader* pReader,
-    long long& pos,
-    unsigned long id_,
-    char*& val)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    long long total, available;
-
-    long hr = pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(available <= total);
-    
-    long len;
-
-    const long long id = ReadUInt(pReader, pos, len);
-    assert(id >= 0);
-    assert(len > 0);
-    assert(len <= 8);
-    assert((pos + len) <= available);
-    
-    if ((unsigned long)id != id_)
-        return false;
-    
-    pos += len;  //consume id
-    
-    const long long size_ = ReadUInt(pReader, pos, len);
-    assert(size_ >= 0);
-    assert(len > 0);
-    assert(len <= 8);
-    assert((pos + len) <= available);
-    
-    pos += len;  //consume length of size of payload
-    assert((pos + size_) <= available);
-
-    const size_t size = static_cast<size_t>(size_);    
-    val = new char[size+1];
-
-    for (size_t i = 0; i < size; ++i)
-    {
-        char c;
-
-        hr = pReader->Read(pos + i, 1, (unsigned char*)&c);
-        assert(hr == 0L);
-            
-        val[i] = c;
-   
-        if (c == '\0')
-            break;     
-   
-    }
-
-    val[size] = '\0';
-    pos += size_;  //consume size of payload
-    
-    return true;
-}
-
-#if 0
-bool mkvparser::Match(
-    IMkvReader* pReader,
-    long long& pos,
-    unsigned long id,
-    wchar_t*& val)
-{
-    char* str;
-    
-    if (!Match(pReader, pos, id, str))
-        return false;
-
-    const size_t size = mbstowcs(NULL, str, 0);
-       
-    if (size == 0) 
-        val = NULL;
-    else 
-    { 
-        val = new wchar_t[size+1];
-        mbstowcs(val, str, size);
-        val[size] = L'\0';
-    }
-
-    delete[] str;
-    return true;    
-}
-#endif
-
-
-bool mkvparser::Match(
-    IMkvReader* pReader,
-    long long& pos,
-    unsigned long id_,
-    unsigned char*& val,
-    size_t *optionalSize)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    long long total, available;
-
-    long hr = pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(available <= total);
-    
-    long len;
-    const long long id = ReadUInt(pReader, pos, len);
-    assert(id >= 0);
-    assert(len > 0);
-    assert(len <= 8);
-    assert((pos + len) <= available);
-    
-    if ((unsigned long)id != id_)
-        return false;
-        
-    pos += len;  //consume id
-    
-    const long long size_ = ReadUInt(pReader, pos, len);
-    assert(size_ >= 0);
-    assert(len > 0);
-    assert(len <= 8);
-    assert((pos + len) <= available);
-    
-    pos += len;  //consume length of size of payload
-    assert((pos + size_) <= available);
-
-    const size_t size = static_cast<size_t>(size_);    
-    val = new unsigned char[size];
- 
-    if (optionalSize) {
-        *optionalSize = size;
-    }
-
-    for (size_t i = 0; i < size; ++i)
-    {
-        unsigned char b;
-
-        hr = pReader->Read(pos + i, 1, &b);
-        assert(hr == 0L);
-
-        val[i] = b; 
-    }
-    
-    pos += size_;  //consume size of payload    
-    return true;
-}
-
-
-bool mkvparser::Match(
-    IMkvReader* pReader,
-    long long& pos,
-    unsigned long id_,
-    double& val)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    long long total, available;
-
-    long hr = pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(available <= total);
-    long idlen;
-    const long long id = ReadUInt(pReader, pos, idlen);
-    assert(id >= 0);  //TODO
-    
-    if ((unsigned long)id != id_)
-        return false;
-
-    long sizelen;
-    const long long size = ReadUInt(pReader, pos + idlen, sizelen);
-
-    switch (size)
-    {	
-        case 4:
-        case 8:
-            break;
-        default:
-            return false;
-    }
-
-    pos += idlen + sizelen;  //consume id and size fields
-    assert((pos + size) <= available);
-
-    if (size == 4)
-        val = Unserialize4Float(pReader, pos);
-    else
-    {
-        assert(size == 8);
-        val = Unserialize8Double(pReader, pos);
-    }
-    
-    pos += size;  //consume size of payload
-    
-    return true;
-}
-
-
-bool mkvparser::Match(
-    IMkvReader* pReader,
-    long long& pos,
-    unsigned long id_,
-    short& val)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    long long total, available;
-
-    long hr = pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(available <= total);
-    
-    long len;
-    const long long id = ReadUInt(pReader, pos, len);
-    assert(id >= 0);
-    assert((pos + len) <= available);
-    
-    if ((unsigned long)id != id_)
-        return false;
-        
-    pos += len;  //consume id
-    
-    const long long size = ReadUInt(pReader, pos, len);
-    assert(size <= 2);
-    assert((pos + len) <= available);
-   
-    pos += len;  //consume length of size of payload
-    assert((pos + size) <= available);
-
-    //TODO:
-    // Generalize this to work for any size signed int
-    if (size == 1)
-        val = Unserialize1SInt(pReader, pos);
-    else 
-        val = Unserialize2SInt(pReader, pos);
-        
-    pos += size;  //consume size of payload
-    
-    return true;
-}
-
-
-namespace mkvparser
-{
-
-EBMLHeader::EBMLHeader():
-    m_docType(NULL)
-{
-}
-
-EBMLHeader::~EBMLHeader()
-{
-    delete[] m_docType;
-}
-
-long long EBMLHeader::Parse(
-    IMkvReader* pReader,
-    long long& pos)
-{
-    assert(pReader);
-    
-    long long total, available;
-    
-    long hr = pReader->Length(&total, &available);
-    
-    if (hr < 0) 
-        return hr;
-    
-    pos = 0;    
-    long long end = (1024 < available)? 1024: available;    
-
-    for (;;)
-    {    
-        unsigned char b = 0;
-    
-        while (pos < end)
-        {
-            hr = pReader->Read(pos, 1, &b);
-           
-            if (hr < 0)
-                return hr;
-            
-            if (b == 0x1A)
-                break;
-                
-            ++pos;
-        }
-    
-        if (b != 0x1A)
-        {
-            if ((pos >= 1024) ||
-                (available >= total) || 
-                ((total - available) < 5))
-                  return -1;
-                
-            return available + 5;  //5 = 4-byte ID + 1st byte of size
-        }
-    
-        if ((total - pos) < 5)
-            return E_FILE_FORMAT_INVALID;
-            
-        if ((available - pos) < 5)
-            return pos + 5;  //try again later
-
-        long len;            
-
-        const long long result = ReadUInt(pReader, pos, len);
-        
-        if (result < 0)  //error
-            return result;
-            
-        if (result == 0x0A45DFA3)  //ReadId masks-off length indicator bits
-        {
-            assert(len == 4);
-            pos += len;
-            break;
-        }
-
-        ++pos;  //throw away just the 0x1A byte, and try again
-    }
-        
-    long len;
-    long long result = GetUIntLength(pReader, pos, len);
-    
-    if (result < 0)  //error
-        return result;
-        
-    if (result > 0)  //need more data
-        return result;
-        
-    assert(len > 0);
-    assert(len <= 8);
-    
-    if ((total -  pos) < len)
-        return E_FILE_FORMAT_INVALID;
-    if ((available - pos) < len)
-        return pos + len;  //try again later
-        
-    result = ReadUInt(pReader, pos, len);
-    
-    if (result < 0)  //error
-        return result;
-        
-    pos += len;  //consume u-int
-    
-    if ((total - pos) < result)
-        return E_FILE_FORMAT_INVALID;
-
-    if ((available - pos) < result)
-        return pos + result;
-        
-    end = pos + result;
-    
-    m_version = 1;
-    m_readVersion = 1;
-    m_maxIdLength = 4;
-    m_maxSizeLength = 8;
-    m_docTypeVersion = 1;
-    m_docTypeReadVersion = 1;
-
-    while (pos < end)
-    {
-        if (Match(pReader, pos, 0x0286, m_version))   
-            ;
-        else if (Match(pReader, pos, 0x02F7, m_readVersion))        
-            ;
-        else if (Match(pReader, pos, 0x02F2, m_maxIdLength))        
-            ;
-        else if (Match(pReader, pos, 0x02F3, m_maxSizeLength))      
-            ;
-        else if (Match(pReader, pos, 0x0282, m_docType))            
-            ; 
-        else if (Match(pReader, pos, 0x0287, m_docTypeVersion))     
-            ;
-        else if (Match(pReader, pos, 0x0285, m_docTypeReadVersion)) 
-            ;
-        else
-        {
-            result = ReadUInt(pReader, pos, len);
-            assert(result > 0);
-            assert(len > 0);
-            assert(len <= 8);
-        
-            pos += len;
-            assert(pos < end);
-            
-            result = ReadUInt(pReader, pos, len);
-            assert(result >= 0);
-            assert(len > 0);
-            assert(len <= 8);
-            
-            pos += len + result;
-            assert(pos <= end);
-        }
-    }
-    
-    assert(pos == end);
-        
-    return 0;    
-}
-
-
-Segment::Segment(
-    IMkvReader* pReader,
-    long long start,
-    long long size) :
-    m_pReader(pReader),
-    m_start(start),
-    m_size(size),
-    m_pos(start),
-    m_pInfo(NULL),
-    m_pTracks(NULL),
-    m_clusterCount(0)
-    //m_clusterNumber(0)
-{
-}
-
-
-Segment::~Segment()
-{
-    Cluster** i = m_clusters;
-    Cluster** j = m_clusters + m_clusterCount;
-
-    while (i != j)
-    {
-        Cluster* p = *i++;
-        assert(p);		
-        delete p;
-    } 
-    
-    delete[] m_clusters;
-       
-    delete m_pTracks;
-    delete m_pInfo;
-}
-
-
-long long Segment::CreateInstance(
-    IMkvReader* pReader,
-    long long pos,
-    Segment*& pSegment)
-{
-    assert(pReader);
-    assert(pos >= 0);
-    
-    pSegment = NULL;
-    
-    long long total, available;
-    
-    long hr = pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(available <= total);
-    
-    //I would assume that in practice this loop would execute
-    //exactly once, but we allow for other elements (e.g. Void)
-    //to immediately follow the EBML header.  This is fine for
-    //the source filter case (since the entire file is available),
-    //but in the splitter case over a network we should probably
-    //just give up early.  We could for example decide only to
-    //execute this loop a maximum of, say, 10 times.
-    
-    while (pos < total)
-    {    
-        //Read ID
-        
-        long len;
-        long long result = GetUIntLength(pReader, pos, len);
-        
-        if (result)  //error, or too few available bytes
-            return result;
-            
-        if ((pos + len) > total)
-            return E_FILE_FORMAT_INVALID;
-            
-        if ((pos + len) > available)
-            return pos + len;
-
-        //TODO: if we liberalize the behavior of ReadUInt, we can
-        //probably eliminate having to use GetUIntLength here.
-        const long long id = ReadUInt(pReader, pos, len);
-        
-        if (id < 0)  //error
-            return id;
-            
-        pos += len;  //consume ID
-        
-        //Read Size
-        
-        result = GetUIntLength(pReader, pos, len);
-        
-        if (result)  //error, or too few available bytes
-            return result;
-            
-        if ((pos + len) > total)
-            return E_FILE_FORMAT_INVALID;
-            
-        if ((pos + len) > available)
-            return pos + len;
-
-        //TODO: if we liberalize the behavior of ReadUInt, we can
-        //probably eliminate having to use GetUIntLength here.
-        const long long size = ReadUInt(pReader, pos, len);
-        
-        if (size < 0)
-            return size;
-            
-        pos += len;  //consume length of size of element
-        
-        //Pos now points to start of payload
-        
-        if ((pos + size) > total)
-            return E_FILE_FORMAT_INVALID;
-        
-        if (id == 0x08538067)  //Segment ID
-        {
-            pSegment = new  Segment(pReader, pos, size); 
-            assert(pSegment);  //TODO   
-
-            return 0;    //success
-        }
-        
-        pos += size;  //consume payload
-    }
-    
-    assert(pos == total);
-    
-    pSegment = new Segment(pReader, pos, 0); 
-    assert(pSegment);  //TODO   
-
-    return 0;  //success (sort of)
-}
-
-
-long long Segment::ParseHeaders()
-{
-    //Outermost (level 0) segment object has been constructed, 
-    //and pos designates start of payload.  We need to find the
-    //inner (level 1) elements.
-    long long total, available;
-    
-    long hr = m_pReader->Length(&total, &available);
-    assert(hr >= 0);
-    assert(available <= total);
-    
-    const long long stop = m_start + m_size;
-    assert(stop <= total);
-    assert(m_pos <= stop);
-    
-    bool bQuit = false;
-    while ((m_pos < stop) && !bQuit)
-    {
-        long long pos = m_pos;
-        
-        long len;
-        long long result = GetUIntLength(m_pReader, pos, len);
-        
-        if (result)  //error, or too few available bytes
-            return result;
-            
-        if ((pos + len) > stop)
-            return E_FILE_FORMAT_INVALID;
-            
-        if ((pos + len) > available)
-            return pos + len;
-            
-        const long long idpos = pos;
-        const long long id = ReadUInt(m_pReader, idpos, len);
-        
-        if (id < 0)  //error
-            return id;
-            
-        pos += len;  //consume ID
-        
-        //Read Size
-        result = GetUIntLength(m_pReader, pos, len);
-        
-        if (result)  //error, or too few available bytes
-            return result;
-            
-        if ((pos + len) > stop)
-            return E_FILE_FORMAT_INVALID;
-            
-        if ((pos + len) > available)
-            return pos + len;
-
-        const long long size = ReadUInt(m_pReader, pos, len);
-        
-        if (size < 0)
-            return size;
-            
-        pos += len;  //consume length of size of element
-        
-        //Pos now points to start of payload
-        
-        if ((pos + size) > stop)
-            return E_FILE_FORMAT_INVALID;
-            
-        //We read EBML elements either in total or nothing at all.
-            
-        if ((pos + size) > available)
-            return pos + size;
-        
-        if (id == 0x0549A966)  //Segment Info ID
-        {
-            assert(m_pInfo == NULL);
-            m_pInfo = new  SegmentInfo(this, pos, size);
-            assert(m_pInfo);  //TODO
-            
-            if (m_pTracks)
-                bQuit = true;
-        }
-        else if (id == 0x0654AE6B)  //Tracks ID
-        {
-            assert(m_pTracks == NULL);
-            m_pTracks = new  Tracks(this, pos, size);
-            assert(m_pTracks);  //TODO
-            
-            if (m_pInfo)
-                bQuit = true;
-        }
-        else if (id == 0x0F43B675)  //Cluster ID
-        {
-#if 0
-            if (m_pInfo == NULL)  //TODO: liberalize
-                ;  
-            else if (m_pTracks == NULL)
-                ;
-            else
-                //ParseCluster(idpos, pos, size);            
-                Cluster::Parse(this, m_clusters, pos, size);
-#endif
-            bQuit = true;
-        }
-        
-        m_pos = pos + size;  //consume payload
-    }
-    
-    assert(m_pos <= stop);
-    
-    return 0;  //success
-}
-
-
-long Segment::ParseCluster(Cluster*& pCluster, long long& pos_) const
-{
-    pCluster = NULL;
-    pos_ = -1;
-    
-    const long long stop = m_start + m_size;
-    assert(m_pos <= stop);
-    
-    long long pos = m_pos;
-    long long off = -1;
-   
- 
-    while (pos < stop)
-    {
-        long len;
-        const long long idpos = pos;
-        
-        const long long id = SyncReadUInt(m_pReader, pos, stop, len);
-        
-        if (id < 0)  //error
-            return static_cast<long>(id);
-            
-        if (id == 0)
-            return E_FILE_FORMAT_INVALID;
-            
-        pos += len;  //consume id        
-        assert(pos < stop);
-
-        const long long size = SyncReadUInt(m_pReader, pos, stop, len);
-        
-        if (size < 0)  //error
-            return static_cast<long>(size);
-            
-        pos += len;  //consume size
-        assert(pos <= stop);
-            
-        if (size == 0)  //weird
-            continue;
-            
-        //pos now points to start of payload
-            
-        pos += size;  //consume payload
-        assert(pos <= stop);
-
-        if (off >= 0)
-        {
-            pos_ = idpos;
-            break;
-        }
-
-        if (id == 0x0F43B675)  //Cluster ID
-            off = idpos - m_start;
-    }
-    
-    Segment* const this_ = const_cast<Segment*>(this);
-    const size_t idx = m_clusterCount;
-    
-    if (pos >= stop)
-    {
-        pos_ = stop;
-        
-#if 0        
-        if (off < 0)
-        {
-            pCluster = Cluster::CreateEndOfStream(this_, idx);
-            return 1L;
-        }
-#else
-        if (off < 0)
-            return 1L;
-#endif
-                
-        //Reading 0 bytes at pos might work too -- it would depend 
-        //on how the reader is implemented.
-        
-        unsigned char b;
-
-        const long hr = m_pReader->Read(pos - 1, 1, &b);
-        
-        if (hr < 0)
-            return hr;
-            
-        if (hr != 0L)
-            return E_BUFFER_NOT_FULL;
-    }
-    
-    assert(off >= 0);
-    assert(pos_ >= m_start);
-    assert(pos_ <= stop);
-
-    pCluster = Cluster::Parse(this_, idx, off);
-    return 0L;
-}
-
-
-bool Segment::AddCluster(Cluster* pCluster, long long pos)
-{
-    assert(pos >= m_start);
-    
-    const long long stop = m_start + m_size;
-    assert(pos <= stop);
-
-    if (pCluster)    
-        m_clusters[pos] = pCluster;
-        
-    m_pos = pos;  //m_pos >= stop is now we know we have all clusters
-    
-    return (pos >= stop);
-}
-
-
-long Segment::Load()
-{
-    //Outermost (level 0) segment object has been constructed, 
-    //and pos designates start of payload.  We need to find the
-    //inner (level 1) elements.
-    const long long stop = m_start + m_size;
-#ifdef _DEBUG
-    {
-        long long total, available;
-        
-        long hr = m_pReader->Length(&total, &available);
-        assert(hr >= 0);
-        assert(available >= total);
-        assert(stop <= total);
-    }
-#endif
-    long long index = m_pos;
-    
-    m_clusterCount = 0;
-
-    while (index < stop)
-    {
-        long len = 0;
-
-        long long result = GetUIntLength(m_pReader, index, len);
-       
-        if (result < 0)  //error
-            return static_cast<long>(result);
-            
-        if ((index + len) > stop)
-            return E_FILE_FORMAT_INVALID;
-            
-        const long long idpos = index;
-        const long long id = ReadUInt(m_pReader, idpos, len);
-        
-        if (id < 0)  //error
-            return static_cast<long>(id);
-            
-        index += len;  //consume ID
-        
-        //Read Size
-        result = GetUIntLength(m_pReader, index, len);
-        
-        if (result < 0)  //error
-            return static_cast<long>(result);
-            
-        if ((index + len) > stop)
-            return E_FILE_FORMAT_INVALID;
-            
-        const long long size = ReadUInt(m_pReader, index, len);
-        
-        if (size < 0)  //error
-            return static_cast<long>(size);
-            
-        index += len;  //consume length of size of element
- 
-        if (id == 0x0F43B675) // Cluster ID 
-            break;
-	
-        if (id == 0x014D9B74) // SeekHead ID 
-        {
-            ParseSeekHead(index, size, NULL); 
-            break;
-        }
-        index += size;
-    }
-        
-    if (m_clusterCount == 0)
-        return -1L;
-
-    while (m_pos < stop)
-    {
-        long long pos = m_pos;
-        
-        long len;
-
-        long long result = GetUIntLength(m_pReader, pos, len);
-        
-        if (result < 0)  //error
-            return static_cast<long>(result);
-            
-        if ((pos + len) > stop)
-            return E_FILE_FORMAT_INVALID;
-            
-        const long long idpos = pos;
-        const long long id = ReadUInt(m_pReader, idpos, len);
-        
-        if (id < 0)  //error
-            return static_cast<long>(id);
-            
-        pos += len;  //consume ID
-        
-        //Read Size
-        result = GetUIntLength(m_pReader, pos, len);
-        
-        if (result < 0)  //error
-            return static_cast<long>(result);
-            
-        if ((pos + len) > stop)
-	        return E_FILE_FORMAT_INVALID;
-            
-        const long long size = ReadUInt(m_pReader, pos, len);
-       
-        if (size < 0)  //error
-            return static_cast<long>(size);
-            
-        pos += len;  //consume length of size of element
-        
-        //Pos now points to start of payload
-        
-        if ((pos + size) > stop)
-            return E_FILE_FORMAT_INVALID;
-            
-        if (id == 0x0F43B675)  //Cluster ID
-            break;
-
-        if (id == 0x014D9B74)  //SeekHead ID
-        {
-            m_clusters = new Cluster*[m_clusterCount];   
-            size_t index = 0;
-            
-            ParseSeekHead(pos, size, &index);            
-            assert(index == m_clusterCount);
-        }            
-        else if (id == 0x0549A966)  //Segment Info ID
-        {
-            assert(m_pInfo == NULL);
-            m_pInfo = new  SegmentInfo(this, pos, size);
-            assert(m_pInfo);  //TODO
-        }
-        else if (id == 0x0654AE6B)  //Tracks ID
-        {
-            assert(m_pTracks == NULL);
-            m_pTracks = new Tracks(this, pos, size);
-            assert(m_pTracks);  //TODO
-        }
-
-        m_pos = pos + size;  //consume payload
-    }
-    
-    assert(m_clusters);
-    
-    //TODO: see notes above.  This check is here (temporarily) to ensure
-    //that the first seekhead has entries for the clusters (because that's
-    //when they're loaded).  In case we are given a file that lists the
-    //clusters in a second seekhead, the worst thing that happens is that
-    //we treat this as an invalid file (which is better then simply
-    //asserting somewhere).  But that's only a work-around.  What we need
-    //to do is be able to handle having multiple seekheads, and having
-    //clusters listed somewhere besides the first seekhead.
-    //    
-    //if (m_clusters == NULL)
-    //    return E_FILE_FORMAT_INVALID;
-        
-    //NOTE: we stop parsing when we reach the first cluster, under the
-    //assumption all clusters are named in some SeekHead.  Clusters
-    //will have been (pre)loaded, so we indicate that we have all clusters
-    //by adjusting the parse position:
-    m_pos = stop;  //means "we have all clusters"
-
-    return 0L;
-}
-
-
-void Segment::ParseSeekHead(long long start, long long size_, size_t* pIndex)
-{
-    long long pos = start;
-    const long long stop = start + size_;
-    while (pos < stop)
-    {
-        long len;
-        
-        const long long id = ReadUInt(m_pReader, pos, len);
-        assert(id >= 0);  //TODO
-        assert((pos + len) <= stop);
-        
-        pos += len;  //consume ID
-        
-        const long long size = ReadUInt(m_pReader, pos, len);
-        assert(size >= 0);
-        assert((pos + len) <= stop);
-        
-        pos += len;  //consume Size field
-        assert((pos + size) <= stop);
-
-        if (id == 0x0DBB)  //SeekEntry ID
-            ParseSeekEntry(pos, size, pIndex);
-        
-        pos += size;  //consume payload
-        assert(pos <= stop);
-    }
-    
-    assert(pos == stop);
-}
-
-
-void Segment::ParseSecondarySeekHead(long long off, size_t* pIndex)
-{
-    assert(off >= 0);
-    assert(off < m_size);
-
-    long long pos = m_start + off;
-    const long long stop = m_start + m_size;
-    
-    long len;
-
-    long long result = GetUIntLength(m_pReader, pos, len);
-    assert(result == 0);
-    assert((pos + len) <= stop);
-    
-    const long long idpos = pos;
-
-    const long long id = ReadUInt(m_pReader, idpos, len);
-    assert(id == 0x014D9B74);  //SeekHead ID
-    
-    pos += len;  //consume ID
-    assert(pos < stop);
-    
-    //Read Size
-    
-    result = GetUIntLength(m_pReader, pos, len);
-    assert(result == 0);
-    assert((pos + len) <= stop);
-    
-    const long long size = ReadUInt(m_pReader, pos, len);
-    assert(size >= 0);
-    
-    pos += len;  //consume length of size of element
-    assert((pos + size) <= stop);
-    
-    //Pos now points to start of payload
-    
-    ParseSeekHead(pos, size, pIndex);
-}
-
-
-void Segment::ParseSeekEntry(long long start, long long size_, size_t* pIndex)
-{
-    long long pos = start;
-
-    const long long stop = start + size_;
-    
-    long len;
-    
-    const long long seekIdId = ReadUInt(m_pReader, pos, len);
-    //seekIdId;
-    assert(seekIdId == 0x13AB);  //SeekID ID
-    assert((pos + len) <= stop);
-    
-    pos += len;  //consume id
-
-    const long long seekIdSize = ReadUInt(m_pReader, pos, len);
-    assert(seekIdSize >= 0);
-    assert((pos + len) <= stop);
-    
-    pos += len;  //consume size
-    
-    const long long seekId = ReadUInt(m_pReader, pos, len);  //payload
-    assert(seekId >= 0);
-    assert(len == seekIdSize);
-    assert((pos + len) <= stop);
-    
-    pos += seekIdSize;  //consume payload
-    
-    const long long seekPosId = ReadUInt(m_pReader, pos, len);
-    //seekPosId;
-    assert(seekPosId == 0x13AC);  //SeekPos ID
-    assert((pos + len) <= stop);
-    
-    pos += len;  //consume id
-    
-    const long long seekPosSize = ReadUInt(m_pReader, pos, len);
-    assert(seekPosSize >= 0);
-    assert((pos + len) <= stop);
-
-    pos += len;  //consume size
-    assert((pos + seekPosSize) <= stop);
-        
-    const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize);
-    assert(seekOff >= 0);
-    assert(seekOff < m_size);
-    
-    pos += seekPosSize;  //consume payload
-    assert(pos == stop);
-    
-    const long long seekPos = m_start + seekOff;
-    assert(seekPos < (m_start + m_size));
-   
-    if (seekId == 0x0F43B675)  //cluster id
-    {       
-        if (pIndex == NULL)
-            ++m_clusterCount; 
-        else
-        {
-            assert(m_clusters);
-            assert(m_clusterCount > 0);
-            
-            size_t& index = *pIndex;
-            assert(index < m_clusterCount);
-            
-            Cluster*& pCluster = m_clusters[index];
-            
-            pCluster = Cluster::Parse(this, index, seekOff);
-            assert(pCluster);  //TODO
-            
-            ++index;
-        }
-    }
-    else if (seekId == 0x014D9B74)  //SeekHead ID
-    {
-        ParseSecondarySeekHead(seekOff, pIndex);
-    }
-}
-
-
-long long Segment::Unparsed() const
-{
-    const long long stop = m_start + m_size;
-
-    const long long result = stop - m_pos;
-    assert(result >= 0);
-    
-    return result;
-}
-
-
-#if 0  //NOTE: too inefficient
-long long Segment::Load(long long time_ns)
-{
-    if (Unparsed() <= 0)
-        return 0;
-    
-    while (m_clusters.empty())
-    {
-        const long long result = Parse();
-        
-        if (result)  //error, or not enough bytes available
-            return result;
-            
-        if (Unparsed() <= 0)
-            return 0;
-    }
-    
-    while (m_clusters.back()->GetTime() < time_ns)
-    {
-        const long long result = Parse();
-        
-        if (result)  //error, or not enough bytes available
-            return result;
-            
-        if (Unparsed() <= 0)
-            return 0;
-    }        
-
-    return 0;        
-}
-#endif
-
-
-Cluster* Segment::GetFirst()
-{
-    if ((m_clusters == NULL) || (m_clusterCount <= 0))
-       return &m_eos;
-
-    Cluster* const pCluster = m_clusters[0];
-    assert(pCluster);
-        
-    return pCluster;
-}
-
-
-Cluster* Segment::GetLast()
-{
-    if ((m_clusters == NULL) || (m_clusterCount <= 0))
-        return &m_eos;
-
-    const size_t idx = m_clusterCount - 1;    
-    Cluster* const pCluster = m_clusters[idx];
-    assert(pCluster);
-        
-    return pCluster;
-}
-
-
-unsigned long Segment::GetCount() const
-{
-    //TODO: m_clusterCount should not be long long.
-    return static_cast<unsigned long>(m_clusterCount);
-}
-
-
-Cluster* Segment::GetNext(const Cluster* pCurr)
-{
-    assert(pCurr);
-    assert(pCurr != &m_eos);
-    assert(m_clusters);
-    assert(m_clusterCount > 0);
-
-    size_t idx =  pCurr->m_index;
-    assert(idx < m_clusterCount);
-    assert(pCurr == m_clusters[idx]);
-    
-    idx++;
-    
-    if (idx >= m_clusterCount) 
-        return &m_eos;
-        
-    Cluster* const pNext = m_clusters[idx];
-    assert(pNext);
-    
-    return pNext;
-}
-
-
-Cluster* Segment::GetCluster(long long time_ns)
-{
-    if ((m_clusters == NULL) || (m_clusterCount <= 0))
-        return &m_eos;
-        
-    {
-        Cluster* const pCluster = m_clusters[0];
-        assert(pCluster);
-        assert(pCluster->m_index == 0);
-        
-        if (time_ns <= pCluster->GetTime())
-            return pCluster;
-    }
-    
-    //Binary search of cluster array
-       
-    size_t i = 0;
-    size_t j = m_clusterCount;
-    
-    while (i < j)
-    {
-        //INVARIANT:
-        //[0, i) <= time_ns
-        //[i, j) ?
-        //[j, m_clusterCount)  > time_ns
-        
-        const size_t k = i + (j - i) / 2;
-        assert(k < m_clusterCount);
-
-        Cluster* const pCluster = m_clusters[k];
-        assert(pCluster);
-        assert(pCluster->m_index == k);
-        
-        const long long t = pCluster->GetTime();
-        
-        if (t <= time_ns)
-            i = k + 1;
-        else
-            j = k;
-            
-        assert(i <= j);
-    }
-    
-    assert(i == j);
-    assert(i > 0);
-    assert(i <= m_clusterCount);
-    
-    const size_t k = i - 1;
-    
-    Cluster* const pCluster = m_clusters[k];
-    assert(pCluster);
-    assert(pCluster->m_index == k);
-    assert(pCluster->GetTime() <= time_ns);
-    
-    return pCluster;
-}
-
-
-Tracks* Segment::GetTracks() const
-{
-    return m_pTracks;
-}
-
-
-const SegmentInfo* const Segment::GetInfo() const
-{
-    return m_pInfo;
-}
-
-
-long long Segment::GetDuration() const
-{
-    assert(m_pInfo);
-    return m_pInfo->GetDuration();
-}
-
-
-SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_) :
-    m_pSegment(pSegment),
-    m_start(start),
-    m_size(size_),
-    m_pMuxingAppAsUTF8(NULL),
-    m_pWritingAppAsUTF8(NULL),
-    m_pTitleAsUTF8(NULL)
-{
-    IMkvReader* const pReader = m_pSegment->m_pReader;
-   
-    long long pos = start;
-    const long long stop = start + size_;
-    
-    m_timecodeScale = 1000000;
-    m_duration = 0;
-    
-    
-    while (pos < stop)
-    {
-        if (Match(pReader, pos, 0x0AD7B1, m_timecodeScale))
-            assert(m_timecodeScale > 0);
-
-        else if (Match(pReader, pos, 0x0489, m_duration))
-            assert(m_duration >= 0);
-
-        else if (Match(pReader, pos, 0x0D80, m_pMuxingAppAsUTF8))   //[4D][80] 
-            assert(m_pMuxingAppAsUTF8);
-
-        else if (Match(pReader, pos, 0x1741, m_pWritingAppAsUTF8))  //[57][41]
-            assert(m_pWritingAppAsUTF8);
-            
-        else if (Match(pReader, pos, 0x3BA9, m_pTitleAsUTF8))        //[7B][A9]
-            assert(m_pTitleAsUTF8);
-
-        else
-        {
-            long len;
-            
-            const long long id = ReadUInt(pReader, pos, len);
-            //id;
-            assert(id >= 0);
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume id
-            assert((stop - pos) > 0);
-            
-            const long long size = ReadUInt(pReader, pos, len);
-            assert(size >= 0);
-            assert((pos + len) <= stop);
-            
-            pos += len + size;  //consume size and payload
-            assert(pos <= stop);
-        }
-    }
-    
-    assert(pos == stop);
-}
-
-SegmentInfo::~SegmentInfo()
-{
-    if (m_pMuxingAppAsUTF8)
-    {
-        delete[] m_pMuxingAppAsUTF8;
-        m_pMuxingAppAsUTF8 = NULL;
-    }
-
-    if (m_pWritingAppAsUTF8)
-    {
-        delete[] m_pWritingAppAsUTF8;
-        m_pWritingAppAsUTF8 = NULL;
-    }
-   
-    if (m_pTitleAsUTF8)
-    {
-        delete[] m_pTitleAsUTF8;
-        m_pTitleAsUTF8 = NULL;
-    }
-}
-
-long long SegmentInfo::GetTimeCodeScale() const
-{
-    return m_timecodeScale;
-}
-
-
-long long SegmentInfo::GetDuration() const
-{
-    assert(m_duration >= 0);    
-    assert(m_timecodeScale >= 1);
-    
-    const double dd = double(m_duration) * double(m_timecodeScale);
-    const long long d = static_cast<long long>(dd);
-    
-    return d;
-}
-
-const char* SegmentInfo::GetMuxingAppAsUTF8() const
-{
-    return m_pMuxingAppAsUTF8;
-}
-
-const char* SegmentInfo::GetWritingAppAsUTF8() const
-{
-    return m_pWritingAppAsUTF8;
-}
-
-const char* SegmentInfo::GetTitleAsUTF8() const
-{
-    return m_pTitleAsUTF8;
-}
-
-Track::Track(Segment* pSegment, const Info& i) :
-    m_pSegment(pSegment),
-    m_info(i)
-{
-}
-
-Track::~Track()
-{
-    Info& info = const_cast<Info&>(m_info);
-    info.Clear();
-}
-
-Track::Info::Info():
-    type(-1),
-    number(-1),
-    uid(-1),
-    nameAsUTF8(NULL),
-    codecId(NULL),
-    codecPrivate(NULL),
-    codecPrivateSize(0),
-    codecNameAsUTF8(NULL)
-{
-}
-
-void Track::Info::Clear() 
-{
-    delete[] nameAsUTF8;
-    nameAsUTF8 = NULL;
-
-    delete[] codecId;
-    codecId = NULL;
-
-    delete[] codecPrivate;
-    codecPrivate = NULL;
-
-    delete[] codecNameAsUTF8;
-    codecNameAsUTF8 = NULL;
-}
-
-const BlockEntry* Track::GetEOS() const
-{
-    return &m_eos;
-}
-
-long long Track::GetType() const
-{
-    const unsigned long result = static_cast<unsigned long>(m_info.type);
-    return result;
-}
-
-unsigned long Track::GetNumber() const
-{
-    assert(m_info.number >= 0);
-    const unsigned long result = static_cast<unsigned long>(m_info.number);
-    return result;
-}
-
-const char* Track::GetNameAsUTF8() const
-{
-    return m_info.nameAsUTF8;
-}
-
-const char* Track::GetCodecNameAsUTF8() const
-{  
-    return m_info.codecNameAsUTF8;
-}
-
-
-const char* Track::GetCodecId() const
-{
-    return m_info.codecId;
-}
-
-
-const unsigned char* Track::GetCodecPrivate(size_t *optionalSize) const
-{
-    if (optionalSize) {
-        *optionalSize = m_info.codecPrivateSize;
-    }
-    return m_info.codecPrivate;
-}
-
-
-long Track::GetFirst(const BlockEntry*& pBlockEntry) const
-{
-    Cluster* const pCluster = m_pSegment->GetFirst();
-    
-    //If Segment::GetFirst returns NULL, then this must be a network 
-    //download, and we haven't loaded any clusters yet.  In this case,
-    //returning NULL from Track::GetFirst means the same thing.
-
-    if ((pCluster == NULL) || pCluster->EOS())
-    {
-        pBlockEntry = NULL;
-        return E_BUFFER_NOT_FULL;  //return 1L instead?
-    }
-        
-    pBlockEntry = pCluster->GetFirst();
-    
-    while (pBlockEntry)
-    {
-        const Block* const pBlock = pBlockEntry->GetBlock();
-        assert(pBlock);
-        
-        if (pBlock->GetTrackNumber() == (unsigned long)m_info.number)
-            return 0L;
-            
-        pBlockEntry = pCluster->GetNext(pBlockEntry);
-    }
-    
-    //NOTE: if we get here, it means that we didn't find a block with
-    //a matching track number.  We interpret that as an error (which
-    //might be too conservative).
-
-    pBlockEntry = GetEOS();  //so we can return a non-NULL value
-    return 1L;
-}
-
-
-long Track::GetNext(const BlockEntry* pCurrEntry, const BlockEntry*& pNextEntry) const
-{
-    assert(pCurrEntry);
-    assert(!pCurrEntry->EOS());  //?
-    assert(pCurrEntry->GetBlock()->GetTrackNumber() == (unsigned long)m_info.number);    
-    
-    const Cluster* const pCurrCluster = pCurrEntry->GetCluster();
-    assert(pCurrCluster);
-    assert(!pCurrCluster->EOS());
-    
-    pNextEntry = pCurrCluster->GetNext(pCurrEntry);
-            
-    while (pNextEntry)
-    {    
-        const Block* const pNextBlock = pNextEntry->GetBlock();
-        assert(pNextBlock);
-    
-        if (pNextBlock->GetTrackNumber() == (unsigned long)m_info.number)
-            return 0L;
-            
-        pNextEntry = pCurrCluster->GetNext(pNextEntry);
-    }
-
-    Segment* pSegment = pCurrCluster->m_pSegment;    
-    Cluster* const pNextCluster = pSegment->GetNext(pCurrCluster);
-    
-    if ((pNextCluster == NULL) || pNextCluster->EOS())
-    {
-        if (pSegment->Unparsed() <= 0)   //all clusters have been loaded
-        {
-            pNextEntry = GetEOS();
-            return 1L;
-        }
-        
-        pNextEntry = NULL;
-        return E_BUFFER_NOT_FULL;
-    }
-        
-    pNextEntry = pNextCluster->GetFirst();
-    
-    while (pNextEntry)
-    {
-        const Block* const pNextBlock = pNextEntry->GetBlock();
-        assert(pNextBlock);
-        
-        if (pNextBlock->GetTrackNumber() == (unsigned long)m_info.number)
-            return 0L;
-            
-        pNextEntry = pNextCluster->GetNext(pNextEntry);
-    }
-    
-    //TODO: what has happened here is that we did not find a block
-    //with a matching track number on the next cluster.  It might
-    //be the case that some cluster beyond the next cluster 
-    //contains a block having a matching track number, but for
-    //now we terminate the search immediately.  We do this so that
-    //we don't end up searching the entire file looking for the
-    //next block.  Another possibility is to try searching for the next
-    //block in a small, fixed number of clusters (intead searching
-    //just the next one), or to terminate the search when when the
-    //there is a large gap in time, or large gap in file position.  It
-    //might very well be the case that the approach we use here is
-    //unnecessarily conservative.
-    
-    //TODO: again, here's a case where we need to return the special
-    //EOS block.  Or something.  It's OK if pNext is NULL, because
-    //we only need it to set the stop time of the media sample.
-    //(The start time is determined from pCurr, which is non-NULL
-    //and non-EOS.)  The problem is when we set pCurr=pNext; when
-    //pCurr has the value NULL we interpret that to mean that we
-    //haven't fully initialized pCurr and we attempt to set it to
-    //point to the first block for this track.  But that's not what
-    //we want at all; we want the next call to PopulateSample to
-    //return end-of-stream, not (re)start from the beginning.
-    //
-    //One work-around is to send EOS immediately.  We would send 
-    //the EOS the next pass anyway, so maybe it's no great loss.  The 
-    //only problem is that if this the stream really does end one
-    //cluster early (relative to other tracks), or the last frame
-    //happens to be a keyframe ("CanSeekToEnd").
-    //
-    //The problem is that we need a way to mark as stream as
-    //"at end of stream" without actually being at end of stream.
-    //We need to give pCurr some value that means "you've reached EOS".
-    //We can't synthesize the special EOS Cluster immediately
-    //(when we first open the file, say), because we use the existance
-    //of that special cluster value to mean that we've read all of 
-    //the clusters (this is a network download, so we can't know apriori
-    //how many we have).
-    //
-    //Or, we could return E_FAIL, and set another bit in the stream
-    //object itself, to indicate that it should send EOS earlier
-    //than when (pCurr=pStop).
-    //
-    //Or, probably the best solution, when we actually load the 
-    //blocks into a cluster: if we notice that there's no block
-    //for a track, we synthesize a nonce EOS block for that track.
-    //That way we always have something to return.  But that will
-    //only work for sequential scan???
-
-    //pNext = NULL;    
-    //return E_FAIL;
-    pNextEntry = GetEOS();
-    return 1L;
-}
-
-
-Track::EOSBlock::EOSBlock()
-{
-}
-
-
-bool Track::EOSBlock::EOS() const
-{
-    return true;
-}
-
-
-Cluster* Track::EOSBlock::GetCluster() const
-{
-    return NULL;
-}
-
-
-size_t Track::EOSBlock::GetIndex() const
-{
-    return 0;
-}
-
-
-const Block* Track::EOSBlock::GetBlock() const
-{
-    return NULL;
-}
-
-
-bool Track::EOSBlock::IsBFrame() const
-{
-    return false;
-}
-
-
-VideoTrack::VideoTrack(Segment* pSegment, const Info& i) :
-    Track(pSegment, i),
-    m_width(-1),
-    m_height(-1),
-    m_rate(-1)
-{
-    assert(i.type == 1);
-    assert(i.number > 0);
-    
-    IMkvReader* const pReader = pSegment->m_pReader;
-    
-    const Settings& s = i.settings;
-    assert(s.start >= 0);
-    assert(s.size >= 0);
-    
-    long long pos = s.start;
-    assert(pos >= 0);
-    
-    const long long stop = pos + s.size;
-    
-    while (pos < stop)
-    {
-#ifdef _DEBUG
-        long len;
-        const long long id = ReadUInt(pReader, pos, len);
-        assert(id >= 0);  //TODO: handle error case
-        assert((pos + len) <= stop);
-#endif
-        if (Match(pReader, pos, 0x30, m_width))         
-            ;
-        else if (Match(pReader, pos, 0x3A, m_height))   
-            ;
-        else if (Match(pReader, pos, 0x0383E3, m_rate)) 
-            ;
-        else
-        {
-            long len;
-            const long long id = ReadUInt(pReader, pos, len);
-            assert(id >= 0);  //TODO: handle error case
-            assert((pos + len) <= stop);
-        
-            pos += len;  //consume id
-            
-            const long long size = ReadUInt(pReader, pos, len);
-            assert(size >= 0);  //TODO: handle error case
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume length of size
-            assert((pos + size) <= stop);
-            
-            //pos now designates start of payload
-            
-            pos += size;  //consume payload
-            assert(pos <= stop);
-        }
-    }
-    
-    return;
-}
-
-
-bool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const
-{
-    assert(pBlockEntry);
-    
-    const Block* const pBlock = pBlockEntry->GetBlock();
-    assert(pBlock);    
-    assert(pBlock->GetTrackNumber() == (unsigned long)m_info.number);
-    
-    return pBlock->IsKey();
-}
-
-
-
-long long VideoTrack::GetWidth() const
-{
-    return m_width;
-}
-
-
-long long VideoTrack::GetHeight() const
-{
-    return m_height;
-}
-
-
-double VideoTrack::GetFrameRate() const
-{
-    return m_rate;
-}
-
-
-AudioTrack::AudioTrack(Segment* pSegment, const Info& i) :
-    Track(pSegment, i)
-{
-    assert(i.type == 2);
-    assert(i.number > 0);
-
-    IMkvReader* const pReader = pSegment->m_pReader;
-    
-    const Settings& s = i.settings;
-    assert(s.start >= 0);
-    assert(s.size >= 0);
-    
-    long long pos = s.start;
-    assert(pos >= 0);
-    
-    const long long stop = pos + s.size;
-    
-    while (pos < stop)
-    {
-#ifdef _DEBUG
-        long len;
-        const long long id = ReadUInt(pReader, pos, len);
-        assert(id >= 0);  //TODO: handle error case
-        assert((pos + len) <= stop);
-#endif
-        if (Match(pReader, pos, 0x35, m_rate))            
-            ;
-        else if (Match(pReader, pos, 0x1F, m_channels))   
-            ;
-        else if (Match(pReader, pos, 0x2264, m_bitDepth))  
-            ;            
-        else
-        {
-            long len;
-            const long long id = ReadUInt(pReader, pos, len);
-            assert(id >= 0);  //TODO: handle error case
-            assert((pos + len) <= stop);
-        
-            pos += len;  //consume id
-            
-            const long long size = ReadUInt(pReader, pos, len);
-            assert(size >= 0);  //TODO: handle error case
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume length of size
-            assert((pos + size) <= stop);
-            
-            //pos now designates start of payload
-            
-            pos += size;  //consume payload
-            assert(pos <= stop);
-        }
-    }
-
-    return;
-}
-
-bool AudioTrack::VetEntry(const BlockEntry* pBlockEntry) const
-{
-    assert(pBlockEntry);
-    
-    const Block* const pBlock = pBlockEntry->GetBlock();
-    assert(pBlock);
-    assert(pBlock->GetTrackNumber() == (unsigned long)m_info.number);
-
-    return true;
-}
-
-
-double AudioTrack::GetSamplingRate() const
-{
-    return m_rate;
-}
-
-
-long long AudioTrack::GetChannels() const
-{
-    return m_channels;
-}
-
-long long AudioTrack::GetBitDepth() const
-{
-    return m_bitDepth;
-}
-
-Tracks::Tracks(Segment* pSegment, long long start, long long size_) :
-    m_pSegment(pSegment),
-    m_start(start),
-    m_size(size_),
-    m_trackEntries(NULL),
-    m_trackEntriesEnd(NULL)
-{
-    long long stop = m_start + m_size;
-    IMkvReader* const pReader = m_pSegment->m_pReader;
-    
-    long long pos1 = m_start;
-    int count = 0;
-    
-    while (pos1 < stop)
-    {
-        long len;
-        const long long id = ReadUInt(pReader, pos1, len);
-        assert(id >= 0);
-        assert((pos1 + len) <= stop);
-        
-        pos1 += len;  //consume id
-        
-        const long long size = ReadUInt(pReader, pos1, len);
-        assert(size >= 0);
-        assert((pos1 + len) <= stop);
-        
-        pos1 += len;  //consume length of size
-        
-        //pos now desinates start of element
-        if (id == 0x2E)  //TrackEntry ID
-            ++count;
-            
-        pos1 += size;  //consume payload
-        assert(pos1 <= stop);
-    }    
-
-    if (count <= 0)
-        return;
-
-    m_trackEntries = new Track*[count];
-    m_trackEntriesEnd = m_trackEntries;
-
-    long long pos = m_start;
-
-    while (pos < stop)
-    {
-        long len;
-        const long long id = ReadUInt(pReader, pos, len);
-        assert(id >= 0);
-        assert((pos + len) <= stop);
-        
-        pos += len;  //consume id
-        
-        const long long size1 = ReadUInt(pReader, pos, len);
-        assert(size1 >= 0);
-        assert((pos + len) <= stop);
-        
-        pos += len;  //consume length of size
-        
-        //pos now desinates start of element
-        
-        if (id == 0x2E)  //TrackEntry ID
-            ParseTrackEntry(pos, size1, *m_trackEntriesEnd++);
-            
-        pos += size1;  //consume payload
-        assert(pos <= stop);
-    }    
-}
-
-unsigned long Tracks::GetTracksCount() const
-{
-    const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries;
-    assert(result >= 0);
-    
-    return static_cast<unsigned long>(result);
-}
-
-
-void Tracks::ParseTrackEntry(
-    long long start,
-    long long size,
-    Track*& pTrack)
-{
-    IMkvReader* const pReader = m_pSegment->m_pReader;
-    
-    long long pos = start;
-    const long long stop = start + size;
-
-    Track::Info i;
-    
-    Track::Settings videoSettings;
-    videoSettings.start = -1;
-    
-    Track::Settings audioSettings;
-    audioSettings.start = -1;
-    
-    while (pos < stop)
-    {
-#ifdef _DEBUG
-        long len;
-        const long long id = ReadUInt(pReader, pos, len);
-        len;
-        id;
-#endif
-        if (Match(pReader, pos, 0x57, i.number))
-            assert(i.number > 0);
-
-        else if (Match(pReader, pos, 0x33C5, i.uid))           
-            ;  
-
-        else if (Match(pReader, pos, 0x03, i.type))            
-            ;  
-
-        else if (Match(pReader, pos, 0x136E, i.nameAsUTF8))          
-            assert(i.nameAsUTF8);  
-
-        else if (Match(pReader, pos, 0x06, i.codecId))         
-            ;  
-
-        else if (Match(pReader, pos, 0x23A2, i.codecPrivate, &i.codecPrivateSize))  
-            ;  
-
-        else if (Match(pReader, pos, 0x058688, i.codecNameAsUTF8))   
-            assert(i.codecNameAsUTF8);  
-
-        else
-        {
-            long len;
-            
-            const long long id = ReadUInt(pReader, pos, len);
-            assert(id >= 0);  //TODO: handle error case
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume id
-            
-            const long long size = ReadUInt(pReader, pos, len);
-            assert(size >= 0);  //TODO: handle error case
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume length of size
-            const long long start = pos;
-            
-            pos += size;  //consume payload
-            assert(pos <= stop);
-            
-            if (id == 0x60)
-            {
-                videoSettings.start = start;
-                videoSettings.size = size;
-            }
-            else if (id == 0x61)
-            {
-                audioSettings.start = start;
-                audioSettings.size = size;
-            }
-        }
-    }
-    
-    assert(pos == stop);
-    //TODO: propertly vet info.number, to ensure both its existence,
-    //and that it is unique among all tracks.
-    assert(i.number > 0);
-
-    //TODO: vet settings, to ensure that video settings (0x60)
-    //were specified when type = 1, and that audio settings (0x61)
-    //were specified when type = 2.    
-    if (i.type == 1)  //video
-    {
-        assert(audioSettings.start < 0);
-        assert(videoSettings.start >= 0);
-        
-        i.settings = videoSettings;
-        
-        VideoTrack* const t = new VideoTrack(m_pSegment, i);
-        assert(t);  //TODO
-        pTrack = t;    
-    }
-    else if (i.type == 2)  //audio
-    {
-        assert(videoSettings.start < 0);
-        assert(audioSettings.start >= 0);
-        
-        i.settings = audioSettings;
-        
-        AudioTrack* const t = new  AudioTrack(m_pSegment, i);
-        assert(t);  //TODO
-        pTrack = t;  
-    }
-    else
-    {
-        // for now we do not support other track types yet.
-        // TODO: support other track types
-        i.Clear();
-  
-        pTrack = NULL;
-    }
-    
-    return;
-}
-
-
-Tracks::~Tracks()
-{
-    Track** i = m_trackEntries;
-    Track** const j = m_trackEntriesEnd;
-    
-    while (i != j)
-    {
-        Track* pTrack = *i++;
-        delete pTrack;
-        pTrack = NULL;    
-    }
-
-    delete[] m_trackEntries;
-}
-
-
-Track* Tracks::GetTrackByNumber(unsigned long tn) const
-{
-    Track** i = m_trackEntries;
-    Track** const j = m_trackEntriesEnd;
-
-    while (i != j)
-    {
-        Track* const pTrack = *i++;
-       
-        if (pTrack == NULL)
-            continue;
-
-        if (tn == pTrack->GetNumber())
-            return pTrack;
-    }
-
-    return NULL;  //not found
-}
-
-
-Track* Tracks::GetTrackByIndex(unsigned long idx) const
-{
-    const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries;
-       
-    if (idx >= static_cast<unsigned long>(count))
-         return NULL;
-
-    return m_trackEntries[idx];
-}
-
-
-void Cluster::Load()
-{
-    assert(m_pSegment);
-    
-    if (m_start > 0)
-    {
-        assert(m_size > 0);
-        assert(m_timecode >= 0);
-        return;
-    }
-    
-    assert(m_size == 0);
-    assert(m_timecode < 0);
-    
-    IMkvReader* const pReader = m_pSegment->m_pReader;
-
-    const long long off = -m_start;  //relative to segment
-    long long pos = m_pSegment->m_start + off;  //absolute
-    
-    long len;
-
-    const long long id_ = ReadUInt(pReader, pos, len);
-    assert(id_ >= 0);
-    assert(id_ == 0x0F43B675);  //Cluster ID
-    
-    pos += len;  //consume id
-    
-    const long long size_ = ReadUInt(pReader, pos, len);
-    assert(size_ >= 0);
-    
-    pos += len;  //consume size
-    
-    m_start = pos;
-    m_size = size_;
-    
-    const long long stop = m_start + size_;
-    
-    long long timecode = -1;
-    
-    while (pos < stop)
-    {
-        if (Match(pReader, pos, 0x67, timecode))
-            break;            
-        else
-        {
-            const long long id = ReadUInt(pReader, pos, len);
-            assert(id >= 0);  //TODO
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume id
-            
-            const long long size = ReadUInt(pReader, pos, len);
-            assert(size >= 0);  //TODO
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume size
-            
-            if (id == 0x20)  //BlockGroup ID
-                break;
-                
-            if (id == 0x23)  //SimpleBlock ID
-                break;
-
-            pos += size;  //consume payload
-            assert(pos <= stop);
-        }
-    }
-    
-    assert(pos <= stop);
-    assert(timecode >= 0);
-    
-    m_timecode = timecode;
-}
-
-
-Cluster* Cluster::Parse(
-    Segment* pSegment,
-    size_t idx,
-    long long off)
-{
-    assert(pSegment);
-    assert(off >= 0);
-    assert(off < pSegment->m_size);
-    Cluster* const pCluster = new Cluster(pSegment, idx, -off);
-    assert(pCluster);
-    
-    return pCluster;
-}
-
-
-Cluster::Cluster() :
-    m_pSegment(NULL),
-    m_index(0),
-    m_start(0),
-    m_size(0),
-    m_timecode(0),
-    m_pEntries(NULL),
-    m_entriesCount(0)
-{
-}
-
-Cluster::Cluster(
-    Segment* pSegment,
-    size_t idx,
-    long long off) :
-    m_pSegment(pSegment),
-    m_index(idx),
-    m_start(off),
-    m_size(0),
-    m_timecode(-1),
-    m_pEntries(NULL),
-    m_entriesCount(0)
-{
-}
-
-
-Cluster::~Cluster()
-{
-#if 0
-    while (!m_pEntries.empty())
-    {
-        BlockEntry* pBlockEntry = m_pEntries.front();
-        assert(pBlockEntry);
-        
-        m_pEntries.pop_front();
-        delete pBlockEntry;
-    }
-#else
-    BlockEntry** i = m_pEntries;
-    BlockEntry** const j = m_pEntries + m_entriesCount;
-    while (i != j)
-    {
-         BlockEntry* p = *i++;
-   
-         assert(p);
-         delete p;
-    }
- 
-    delete[] m_pEntries;
-#endif
-
-}
-
-bool Cluster::EOS() const
-{
-    return (m_pSegment == 0);
-}
-
-
-void Cluster::LoadBlockEntries()
-{
-    if (m_pEntries)
-        return;
-
-    Load();    
-    assert(m_timecode >= 0);
-    assert(m_start > 0);
-    assert(m_size > 0);
-    
-    IMkvReader* const pReader = m_pSegment->m_pReader;
-    
-    long long pos = m_start;
-    const long long stop = m_start + m_size;
-    long long timecode = -1;
-   
-    long long idx = pos;
-
-    m_entriesCount = 0;
-    
-    while (idx < stop)
-    {
-        if (Match(pReader, idx, 0x67, timecode))
-            assert(timecode == m_timecode);
-        else 
-        {
-            long len;
-            
-            const long long id = ReadUInt(pReader, idx, len);
-            assert(id >= 0);  //TODO
-            assert((idx + len) <= stop);
-            
-            idx += len;  //consume id
-            
-            const long long size = ReadUInt(pReader, idx, len);
-            assert(size >= 0);  //TODO
-            assert((idx + len) <= stop);
-            
-            idx += len;  //consume size
-            
-            if (id == 0x20)  //BlockGroup ID
-                ++m_entriesCount;
-            else if (id == 0x23)  //SimpleBlock ID
-                ++m_entriesCount;
-
-            idx += size;  //consume payload
-
-            assert(idx <= stop);
-        }  
-    }
-
-    if (m_entriesCount == 0)
-        return;
-     
-    m_pEntries = new BlockEntry*[m_entriesCount];
-    size_t index = 0;
-    
-    while (pos < stop)
-    {
-        if (Match(pReader, pos, 0x67, timecode))
-            assert(timecode == m_timecode);
-        else
-        {
-            long len;
-            const long long id = ReadUInt(pReader, pos, len);
-            assert(id >= 0);  //TODO
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume id
-            
-            const long long size = ReadUInt(pReader, pos, len);
-            assert(size >= 0);  //TODO
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume size
-            
-            if (id == 0x20)  //BlockGroup ID
-                ParseBlockGroup(pos, size, index++);
-            else if (id == 0x23)  //SimpleBlock ID
-                ParseSimpleBlock(pos, size, index++);
-
-            pos += size;  //consume payload
-            assert(pos <= stop);
-        }
-    }
-    
-    assert(pos == stop);
-    assert(timecode >= 0);
-    assert(index == m_entriesCount);
-}
-
-
-
-long long Cluster::GetTimeCode()
-{
-    Load();
-    return m_timecode;
-}
-
-
-long long Cluster::GetTime()
-{
-    const long long tc = GetTimeCode();
-    assert(tc >= 0);
-    
-    const SegmentInfo* const pInfo = m_pSegment->GetInfo();
-    assert(pInfo);
-    
-    const long long scale = pInfo->GetTimeCodeScale();
-    assert(scale >= 1);
-    
-    const long long t = m_timecode * scale;
-
-    return t;
-}
-
-
-void Cluster::ParseBlockGroup(long long start, long long size, size_t index)
-{
-    assert(m_pEntries);
-    assert(m_entriesCount);
-    assert(index < m_entriesCount);
-    
-    BlockGroup* const pGroup = new BlockGroup(this, index, start, size);
-    assert(pGroup);  //TODO
-        
-    m_pEntries[index] = pGroup;
-}
-
-
-
-void Cluster::ParseSimpleBlock(long long start, long long size, size_t index)
-{
-    assert(m_pEntries);
-    assert(m_entriesCount);
-    assert(index < m_entriesCount);
-
-    SimpleBlock* const pSimpleBlock = new SimpleBlock(this, index, start, size);
-    assert(pSimpleBlock);  //TODO
-        
-    m_pEntries[index] = pSimpleBlock;
-}
-
-
-const BlockEntry* Cluster::GetFirst()
-{
-    LoadBlockEntries();
-    
-    return m_pEntries[0];
-}
-
-        
-const BlockEntry* Cluster::GetLast()
-{ 
-    if (m_entriesCount == 0)
-        return m_pEntries[0];
-    
-    return m_pEntries[m_entriesCount-1];
-}
-
-        
-const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const
-{
-    assert(pEntry);
-    
-    size_t idx = pEntry->GetIndex();
-    
-    ++idx;
-
-    if (idx == m_entriesCount) 
-      return NULL;
-
-    return m_pEntries[idx];
-
-}
-
-
-const BlockEntry* Cluster::GetEntry(const Track* pTrack)
-{
-
-    assert(pTrack);
-    
-    if (m_pSegment == NULL)  //EOS
-        return pTrack->GetEOS();
-    
-    LoadBlockEntries();
-    
-    BlockEntry* i = *m_pEntries;
-    BlockEntry* j = *m_pEntries + m_entriesCount;
-    while (i != j)
-    {
-        BlockEntry* pEntry = i;
-        i++;
-        assert(pEntry);
-        assert(!pEntry->EOS());
-        
-        const Block* const pBlock = pEntry->GetBlock();
-        assert(pBlock);
-        
-        if (pBlock->GetTrackNumber() != pTrack->GetNumber())
-            continue;
-
-        if (pTrack->VetEntry(pEntry))
-            return pEntry;
-    }
-    
-    return pTrack->GetEOS();  //no satisfactory block found
-}
-
-
-BlockEntry::BlockEntry()
-{
-}
-
-
-BlockEntry::~BlockEntry()
-{
-}
-
-
-
-SimpleBlock::SimpleBlock(
-    Cluster* pCluster, 
-    size_t idx, 
-    long long start, 
-    long long size) :
-    m_pCluster(pCluster),
-    m_index(idx),
-    m_block(start, size, pCluster->m_pSegment->m_pReader)
-{
-}
-
-
-bool SimpleBlock::EOS() const
-{
-    return false;
-}
-
-
-Cluster* SimpleBlock::GetCluster() const
-{
-    return m_pCluster;
-}
-
-
-size_t SimpleBlock::GetIndex() const
-{
-    return m_index;
-}
-
-
-const Block* SimpleBlock::GetBlock() const
-{
-    return &m_block;
-}
-
-
-bool SimpleBlock::IsBFrame() const
-{
-    return false;
-}
-
-
-BlockGroup::BlockGroup(
-    Cluster* pCluster, 
-    size_t idx, 
-    long long start, 
-    long long size_) :
-    m_pCluster(pCluster),
-    m_index(idx),
-    m_prevTimeCode(0),
-    m_nextTimeCode(0),
-    m_pBlock(NULL)  //TODO: accept multiple blocks within a block group
-{
-    IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;
-    
-    long long pos = start;
-    const long long stop = start + size_;
- 
-    bool bSimpleBlock = false;
-    
-    while (pos < stop)
-    {
-        short t;
-    
-        if (Match(pReader, pos, 0x7B, t))
-        {    
-            if (t < 0)
-                m_prevTimeCode = t;
-            else if (t > 0)
-                m_nextTimeCode = t;
-            else
-                assert(false);
-        }
-        else
-        {
-            long len;
-            const long long id = ReadUInt(pReader, pos, len);
-            assert(id >= 0);  //TODO
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume ID
-            
-            const long long size = ReadUInt(pReader, pos, len);
-            assert(size >= 0);  //TODO
-            assert((pos + len) <= stop);
-            
-            pos += len;  //consume size
-            
-            switch (id)
-            {
-                case 0x23:  //SimpleBlock ID
-                    bSimpleBlock = true;
-                    //YES, FALL THROUGH TO NEXT CASE
-
-                case 0x21:  //Block ID
-                    ParseBlock(pos, size);                    
-                    break;
-                    
-                default:
-                    break;
-            }
-                
-            pos += size;  //consume payload
-            assert(pos <= stop);
-        }
-    }
-    
-    assert(pos == stop);
-    assert(m_pBlock);
-    
-    if (!bSimpleBlock)
-        m_pBlock->SetKey(m_prevTimeCode >= 0);
-}
-
-
-BlockGroup::~BlockGroup()
-{
-    delete m_pBlock;
-}
-
-
-void BlockGroup::ParseBlock(long long start, long long size)
-{   
-    IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;
-    
-    Block* const pBlock = new Block(start, size, pReader);
-    assert(pBlock);  //TODO
-
-    //TODO: the Matroska spec says you have multiple blocks within the 
-    //same block group, with blocks ranked by priority (the flag bits).
-    //I haven't ever seen such a file (mkvmux certainly doesn't make
-    //one), so until then I'll just assume block groups contain a single
-    //block.
-#if 0    
-    m_blocks.push_back(pBlock);
-#else
-    assert(m_pBlock == NULL);
-    m_pBlock = pBlock;
-#endif
-
-#if 0
-    Track* const pTrack = pBlock->GetTrack();
-    assert(pTrack);
-    
-    pTrack->Insert(pBlock);
-#endif
-}
-
-
-bool BlockGroup::EOS() const
-{
-    return false;
-}
-
-
-Cluster* BlockGroup::GetCluster() const
-{
-    return m_pCluster;
-}
-
-
-size_t BlockGroup::GetIndex() const
-{
-    return m_index;
-}
-
-
-const Block* BlockGroup::GetBlock() const
-{
-    return m_pBlock;
-}
-
-
-short BlockGroup::GetPrevTimeCode() const
-{
-    return m_prevTimeCode;
-}
-
-
-short BlockGroup::GetNextTimeCode() const
-{
-    return m_nextTimeCode;
-}    
-
-
-bool BlockGroup::IsBFrame() const
-{
-    return (m_nextTimeCode > 0);
-}
-
-
-
-Block::Block(long long start, long long size_, IMkvReader* pReader) :
-    m_start(start),
-    m_size(size_)
-{
-    long long pos = start;
-    const long long stop = start + size_;
-
-    long len;
-    
-    m_track = ReadUInt(pReader, pos, len);
-    assert(m_track > 0);
-    assert((pos + len) <= stop);
-    
-    pos += len;  //consume track number
-    assert((stop - pos) >= 2);
-    
-    m_timecode = Unserialize2SInt(pReader, pos);
-
-    pos += 2;
-    assert((stop - pos) >= 1);
-    
-    const long hr = pReader->Read(pos, 1, &m_flags);
-    assert(hr == 0L);
-
-    ++pos;
-    assert(pos <= stop);
-    
-    m_frameOff = pos;
-    
-    const long long frame_size = stop - pos;
-
-    assert(frame_size <= 2147483647L);
-    
-    m_frameSize = static_cast<long>(frame_size);
-}
-
-
-long long Block::GetTimeCode(Cluster* pCluster) const
-{
-    assert(pCluster);
-    
-    const long long tc0 = pCluster->GetTimeCode();
-    assert(tc0 >= 0);
-    
-    const long long tc = tc0 + static_cast<long long>(m_timecode);
-    assert(tc >= 0);
-    
-    return tc;  //unscaled timecode units
-}
-
-
-long long Block::GetTime(Cluster* pCluster) const
-{
-    assert(pCluster);
-    
-    const long long tc = GetTimeCode(pCluster);
-    
-    const Segment* const pSegment = pCluster->m_pSegment;
-    const SegmentInfo* const pInfo = pSegment->GetInfo();
-    assert(pInfo);
-    
-    const long long scale = pInfo->GetTimeCodeScale();
-    assert(scale >= 1);
-    
-    const long long ns = tc * scale;
-
-    return ns;
-}
-
-
-unsigned long Block::GetTrackNumber() const
-{
-    assert(m_track > 0);
-    
-    return static_cast<unsigned long>(m_track);
-}
-
-
-bool Block::IsKey() const
-{
-    return ((m_flags & static_cast<unsigned char>(1 << 7)) != 0);
-}
-
-
-void Block::SetKey(bool bKey)
-{
-    if (bKey)
-        m_flags |= static_cast<unsigned char>(1 << 7);
-    else
-        m_flags &= 0x7F;
-}
-
-
-long Block::GetSize() const
-{
-    return m_frameSize;
-}
-
-
-long Block::Read(IMkvReader* pReader, unsigned char* buf) const
-{
-
-    assert(pReader);
-    assert(buf);
-    
-    const long hr = pReader->Read(m_frameOff, m_frameSize, buf);
-    
-    return hr;
-}
-
-
-}  //end namespace mkvparser
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.

+//

+// Use of this source code is governed by a BSD-style license

+// that can be found in the LICENSE file in the root of the source

+// tree. An additional intellectual property rights grant can be found

+// in the file PATENTS.  All contributing project authors may

+// be found in the AUTHORS file in the root of the source tree.

+

+#include "mkvparser.hpp"

+#include <cassert>

+#include <cstring>

+#include <new>

+//#include <windows.h>

+//#include "odbgstream.hpp"

+//using std::endl;

+

+mkvparser::IMkvReader::~IMkvReader()

+{

+}

+

+

+void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision)

+{

+    major = 1;

+    minor = 0;

+    build = 0;

+    revision = 4;

+}

+

+

+long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(pos < available);

+    assert((available - pos) >= 1);  //assume here max u-int len is 8

+

+    unsigned char b;

+

+    hr = pReader->Read(pos, 1, &b);

+    if (hr < 0)

+        return hr;

+

+    assert(hr == 0L);

+

+    if (b & 0x80)       //1000 0000

+    {

+        len = 1;

+        b &= 0x7F;      //0111 1111

+    }

+    else if (b & 0x40)  //0100 0000

+    {

+        len = 2;

+        b &= 0x3F;      //0011 1111

+    }

+    else if (b & 0x20)  //0010 0000

+    {

+        len = 3;

+        b &= 0x1F;      //0001 1111

+    }

+    else if (b & 0x10)  //0001 0000

+    {

+        len = 4;

+        b &= 0x0F;      //0000 1111

+    }

+    else if (b & 0x08)  //0000 1000

+    {

+        len = 5;

+        b &= 0x07;      //0000 0111

+    }

+    else if (b & 0x04)  //0000 0100

+    {

+        len = 6;

+        b &= 0x03;      //0000 0011

+    }

+    else if (b & 0x02)  //0000 0010

+    {

+        len = 7;

+        b &= 0x01;      //0000 0001

+    }

+    else

+    {

+        assert(b & 0x01);  //0000 0001

+        len = 8;

+        b = 0;             //0000 0000

+    }

+

+    assert((available - pos) >= len);

+

+    long long result = b;

+    ++pos;

+    for (long i = 1; i < len; ++i)

+    {

+        hr = pReader->Read(pos, 1, &b);

+

+        if (hr < 0)

+            return hr;

+

+        assert(hr == 0L);

+

+        result <<= 8;

+        result |= b;

+

+        ++pos;

+    }

+

+    return result;

+}

+

+

+long long mkvparser::GetUIntLength(

+    IMkvReader* pReader,

+    long long pos,

+    long& len)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(available <= total);

+

+    if (pos >= available)

+        return pos;  //too few bytes available

+

+    unsigned char b;

+

+    hr = pReader->Read(pos, 1, &b);

+

+    if (hr < 0)

+        return hr;

+

+    assert(hr == 0L);

+

+    if (b == 0)  //we can't handle u-int values larger than 8 bytes

+        return E_FILE_FORMAT_INVALID;

+

+    unsigned char m = 0x80;

+    len = 1;

+

+    while (!(b & m))

+    {

+        m >>= 1;

+        ++len;

+    }

+

+    return 0;  //success

+}

+

+

+long long mkvparser::SyncReadUInt(

+    IMkvReader* pReader,

+    long long pos,

+    long long stop,

+    long& len)

+{

+    assert(pReader);

+

+    if (pos >= stop)

+        return E_FILE_FORMAT_INVALID;

+

+    unsigned char b;

+

+    long hr = pReader->Read(pos, 1, &b);

+

+    if (hr < 0)

+        return hr;

+

+    if (hr != 0L)

+        return E_BUFFER_NOT_FULL;

+

+    if (b == 0)  //we can't handle u-int values larger than 8 bytes

+        return E_FILE_FORMAT_INVALID;

+

+    unsigned char m = 0x80;

+    len = 1;

+

+    while (!(b & m))

+    {

+        m >>= 1;

+        ++len;

+    }

+

+    if ((pos + len) > stop)

+        return E_FILE_FORMAT_INVALID;

+

+    long long result = b & (~m);

+    ++pos;

+

+    for (int i = 1; i < len; ++i)

+    {

+        hr = pReader->Read(pos, 1, &b);

+

+        if (hr < 0)

+            return hr;

+

+        if (hr != 0L)

+            return E_BUFFER_NOT_FULL;

+

+        result <<= 8;

+        result |= b;

+

+        ++pos;

+    }

+

+    return result;

+}

+

+

+long long mkvparser::UnserializeUInt(

+    IMkvReader* pReader,

+    long long pos,

+    long long size)

+{

+    assert(pReader);

+    assert(pos >= 0);

+    assert(size > 0);

+    assert(size <= 8);

+

+    long long result = 0;

+

+    for (long long i = 0; i < size; ++i)

+    {

+        unsigned char b;

+

+        const long hr = pReader->Read(pos, 1, &b);

+

+        if (hr < 0)

+            return hr;

+        result <<= 8;

+        result |= b;

+

+        ++pos;

+    }

+

+    return result;

+}

+

+

+float mkvparser::Unserialize4Float(

+    IMkvReader* pReader,

+    long long pos)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(available <= total);

+    assert((pos + 4) <= available);

+

+    float result;

+

+    unsigned char* const p = (unsigned char*)&result;

+    unsigned char* q = p + 4;

+

+    for (;;)

+    {

+        hr = pReader->Read(pos, 1, --q);

+        assert(hr == 0L);

+

+        if (q == p)

+            break;

+

+        ++pos;

+    }

+

+    return result;

+}

+

+

+double mkvparser::Unserialize8Double(

+    IMkvReader* pReader,

+    long long pos)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    double result;

+

+    unsigned char* const p = (unsigned char*)&result;

+    unsigned char* q = p + 8;

+

+    for (;;)

+    {

+        const long hr = pReader->Read(pos, 1, --q);

+        assert(hr == 0L);

+

+        if (q == p)

+            break;

+

+        ++pos;

+    }

+

+    return result;

+}

+

+signed char mkvparser::Unserialize1SInt(

+    IMkvReader* pReader,

+    long long pos)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr == 0);

+    assert(available <= total);

+    assert(pos < available);

+

+    signed char result;

+

+    hr = pReader->Read(pos, 1, (unsigned char*)&result);

+    assert(hr == 0);

+

+    return result;

+}

+

+short mkvparser::Unserialize2SInt(

+    IMkvReader* pReader,

+    long long pos)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(available <= total);

+    assert((pos + 2) <= available);

+

+    short result;

+

+    unsigned char* const p = (unsigned char*)&result;

+    unsigned char* q = p + 2;

+

+    for (;;)

+    {

+        hr = pReader->Read(pos, 1, --q);

+        assert(hr == 0L);

+

+        if (q == p)

+            break;

+

+        ++pos;

+    }

+

+    return result;

+}

+

+

+bool mkvparser::Match(

+    IMkvReader* pReader,

+    long long& pos,

+    unsigned long id_,

+    long long& val)

+

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(available <= total);

+

+    long len;

+

+    const long long id = ReadUInt(pReader, pos, len);

+    assert(id >= 0);

+    assert(len > 0);

+    assert(len <= 8);

+    assert((pos + len) <= available);

+

+    if ((unsigned long)id != id_)

+        return false;

+

+    pos += len;  //consume id

+

+    const long long size = ReadUInt(pReader, pos, len);

+    assert(size >= 0);

+    assert(size <= 8);

+    assert(len > 0);

+    assert(len <= 8);

+    assert((pos + len) <= available);

+

+    pos += len;  //consume length of size of payload

+

+    val = UnserializeUInt(pReader, pos, size);

+    assert(val >= 0);

+

+    pos += size;  //consume size of payload

+

+    return true;

+}

+

+bool mkvparser::Match(

+    IMkvReader* pReader,

+    long long& pos,

+    unsigned long id_,

+    char*& val)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(available <= total);

+

+    long len;

+

+    const long long id = ReadUInt(pReader, pos, len);

+    assert(id >= 0);

+    assert(len > 0);

+    assert(len <= 8);

+    assert((pos + len) <= available);

+

+    if ((unsigned long)id != id_)

+        return false;

+

+    pos += len;  //consume id

+

+    const long long size_ = ReadUInt(pReader, pos, len);

+    assert(size_ >= 0);

+    assert(len > 0);

+    assert(len <= 8);

+    assert((pos + len) <= available);

+

+    pos += len;  //consume length of size of payload

+    assert((pos + size_) <= available);

+

+    const size_t size = static_cast<size_t>(size_);

+    val = new char[size+1];

+

+    for (size_t i = 0; i < size; ++i)

+    {

+        char c;

+

+        hr = pReader->Read(pos + i, 1, (unsigned char*)&c);

+        assert(hr == 0L);

+

+        val[i] = c;

+

+        if (c == '\0')

+            break;

+

+    }

+

+    val[size] = '\0';

+    pos += size_;  //consume size of payload

+

+    return true;

+}

+

+bool mkvparser::Match(

+    IMkvReader* pReader,

+    long long& pos,

+    unsigned long id_,

+    unsigned char*& buf,

+    size_t& buflen)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(available <= total);

+

+    long len;

+    const long long id = ReadUInt(pReader, pos, len);

+    assert(id >= 0);

+    assert(len > 0);

+    assert(len <= 8);

+    assert((pos + len) <= available);

+

+    if ((unsigned long)id != id_)

+        return false;

+

+    pos += len;  //consume id

+

+    const long long size_ = ReadUInt(pReader, pos, len);

+    assert(size_ >= 0);

+    assert(len > 0);

+    assert(len <= 8);

+    assert((pos + len) <= available);

+

+    pos += len;  //consume length of size of payload

+    assert((pos + size_) <= available);

+

+    const long buflen_ = static_cast<long>(size_);

+

+    buf = new (std::nothrow) unsigned char[buflen_];

+    assert(buf);  //TODO

+

+    hr = pReader->Read(pos, buflen_, buf);

+    assert(hr == 0L);

+

+    buflen = buflen_;

+

+    pos += size_;  //consume size of payload

+    return true;

+}

+

+

+bool mkvparser::Match(

+    IMkvReader* pReader,

+    long long& pos,

+    unsigned long id_,

+    double& val)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(available <= total);

+    long idlen;

+    const long long id = ReadUInt(pReader, pos, idlen);

+    assert(id >= 0);  //TODO

+

+    if ((unsigned long)id != id_)

+        return false;

+

+    long sizelen;

+    const long long size = ReadUInt(pReader, pos + idlen, sizelen);

+

+    switch (size)

+    {

+        case 4:

+        case 8:

+            break;

+        default:

+            return false;

+    }

+

+    pos += idlen + sizelen;  //consume id and size fields

+    assert((pos + size) <= available);

+

+    if (size == 4)

+        val = Unserialize4Float(pReader, pos);

+    else

+    {

+        assert(size == 8);

+        val = Unserialize8Double(pReader, pos);

+    }

+

+    pos += size;  //consume size of payload

+

+    return true;

+}

+

+

+bool mkvparser::Match(

+    IMkvReader* pReader,

+    long long& pos,

+    unsigned long id_,

+    short& val)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(available <= total);

+

+    long len;

+    const long long id = ReadUInt(pReader, pos, len);

+    assert(id >= 0);

+    assert((pos + len) <= available);

+

+    if ((unsigned long)id != id_)

+        return false;

+

+    pos += len;  //consume id

+

+    const long long size = ReadUInt(pReader, pos, len);

+    assert(size <= 2);

+    assert((pos + len) <= available);

+

+    pos += len;  //consume length of size of payload

+    assert((pos + size) <= available);

+

+    //TODO:

+    // Generalize this to work for any size signed int

+    if (size == 1)

+        val = Unserialize1SInt(pReader, pos);

+    else

+        val = Unserialize2SInt(pReader, pos);

+

+    pos += size;  //consume size of payload

+

+    return true;

+}

+

+

+namespace mkvparser

+{

+

+EBMLHeader::EBMLHeader():

+    m_docType(NULL)

+{

+}

+

+EBMLHeader::~EBMLHeader()

+{

+    delete[] m_docType;

+}

+

+long long EBMLHeader::Parse(

+    IMkvReader* pReader,

+    long long& pos)

+{

+    assert(pReader);

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+

+    if (hr < 0)

+        return hr;

+

+    pos = 0;

+    long long end = (1024 < available)? 1024: available;

+

+    for (;;)

+    {

+        unsigned char b = 0;

+

+        while (pos < end)

+        {

+            hr = pReader->Read(pos, 1, &b);

+

+            if (hr < 0)

+                return hr;

+

+            if (b == 0x1A)

+                break;

+

+            ++pos;

+        }

+

+        if (b != 0x1A)

+        {

+            if ((pos >= 1024) ||

+                (available >= total) ||

+                ((total - available) < 5))

+                  return -1;

+

+            return available + 5;  //5 = 4-byte ID + 1st byte of size

+        }

+

+        if ((total - pos) < 5)

+            return E_FILE_FORMAT_INVALID;

+

+        if ((available - pos) < 5)

+            return pos + 5;  //try again later

+

+        long len;

+

+        const long long result = ReadUInt(pReader, pos, len);

+

+        if (result < 0)  //error

+            return result;

+

+        if (result == 0x0A45DFA3)  //ReadId masks-off length indicator bits

+        {

+            assert(len == 4);

+            pos += len;

+            break;

+        }

+

+        ++pos;  //throw away just the 0x1A byte, and try again

+    }

+

+    long len;

+    long long result = GetUIntLength(pReader, pos, len);

+

+    if (result < 0)  //error

+        return result;

+

+    if (result > 0)  //need more data

+        return result;

+

+    assert(len > 0);

+    assert(len <= 8);

+

+    if ((total -  pos) < len)

+        return E_FILE_FORMAT_INVALID;

+    if ((available - pos) < len)

+        return pos + len;  //try again later

+

+    result = ReadUInt(pReader, pos, len);

+

+    if (result < 0)  //error

+        return result;

+

+    pos += len;  //consume u-int

+

+    if ((total - pos) < result)

+        return E_FILE_FORMAT_INVALID;

+

+    if ((available - pos) < result)

+        return pos + result;

+

+    end = pos + result;

+

+    m_version = 1;

+    m_readVersion = 1;

+    m_maxIdLength = 4;

+    m_maxSizeLength = 8;

+    m_docTypeVersion = 1;

+    m_docTypeReadVersion = 1;

+

+    while (pos < end)

+    {

+        if (Match(pReader, pos, 0x0286, m_version))

+            ;

+        else if (Match(pReader, pos, 0x02F7, m_readVersion))

+            ;

+        else if (Match(pReader, pos, 0x02F2, m_maxIdLength))

+            ;

+        else if (Match(pReader, pos, 0x02F3, m_maxSizeLength))

+            ;

+        else if (Match(pReader, pos, 0x0282, m_docType))

+            ;

+        else if (Match(pReader, pos, 0x0287, m_docTypeVersion))

+            ;

+        else if (Match(pReader, pos, 0x0285, m_docTypeReadVersion))

+            ;

+        else

+        {

+            result = ReadUInt(pReader, pos, len);

+            assert(result > 0);

+            assert(len > 0);

+            assert(len <= 8);

+

+            pos += len;

+            assert(pos < end);

+

+            result = ReadUInt(pReader, pos, len);

+            assert(result >= 0);

+            assert(len > 0);

+            assert(len <= 8);

+

+            pos += len + result;

+            assert(pos <= end);

+        }

+    }

+

+    assert(pos == end);

+

+    return 0;

+}

+

+

+Segment::Segment(

+    IMkvReader* pReader,

+    long long start,

+    long long size) :

+    m_pReader(pReader),

+    m_start(start),

+    m_size(size),

+    m_pos(start),

+    m_pInfo(NULL),

+    m_pTracks(NULL),

+    m_pCues(NULL),

+    m_clusters(NULL),

+    m_clusterCount(0),

+    m_clusterPreloadCount(0),

+    m_clusterSize(0)

+{

+}

+

+

+Segment::~Segment()

+{

+    const long count = m_clusterCount + m_clusterPreloadCount;

+

+    Cluster** i = m_clusters;

+    Cluster** j = m_clusters + count;

+

+    while (i != j)

+    {

+        Cluster* const p = *i++;

+        assert(p);

+

+        delete p;

+    }

+

+    delete[] m_clusters;

+

+    delete m_pTracks;

+    delete m_pInfo;

+    delete m_pCues;

+}

+

+

+long long Segment::CreateInstance(

+    IMkvReader* pReader,

+    long long pos,

+    Segment*& pSegment)

+{

+    assert(pReader);

+    assert(pos >= 0);

+

+    pSegment = NULL;

+

+    long long total, available;

+

+    long hr = pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(available <= total);

+

+    //I would assume that in practice this loop would execute

+    //exactly once, but we allow for other elements (e.g. Void)

+    //to immediately follow the EBML header.  This is fine for

+    //the source filter case (since the entire file is available),

+    //but in the splitter case over a network we should probably

+    //just give up early.  We could for example decide only to

+    //execute this loop a maximum of, say, 10 times.

+

+    while (pos < total)

+    {

+        //Read ID

+

+        long len;

+        long long result = GetUIntLength(pReader, pos, len);

+

+        if (result)  //error, or too few available bytes

+            return result;

+

+        if ((pos + len) > total)

+            return E_FILE_FORMAT_INVALID;

+

+        if ((pos + len) > available)

+            return pos + len;

+

+        //TODO: if we liberalize the behavior of ReadUInt, we can

+        //probably eliminate having to use GetUIntLength here.

+        const long long id = ReadUInt(pReader, pos, len);

+

+        if (id < 0)  //error

+            return id;

+

+        pos += len;  //consume ID

+

+        //Read Size

+

+        result = GetUIntLength(pReader, pos, len);

+

+        if (result)  //error, or too few available bytes

+            return result;

+

+        if ((pos + len) > total)

+            return E_FILE_FORMAT_INVALID;

+

+        if ((pos + len) > available)

+            return pos + len;

+

+        //TODO: if we liberalize the behavior of ReadUInt, we can

+        //probably eliminate having to use GetUIntLength here.

+        const long long size = ReadUInt(pReader, pos, len);

+

+        if (size < 0)

+            return size;

+

+        pos += len;  //consume length of size of element

+

+        //Pos now points to start of payload

+

+        if ((pos + size) > total)

+            return E_FILE_FORMAT_INVALID;

+

+        if (id == 0x08538067)  //Segment ID

+        {

+            pSegment = new  Segment(pReader, pos, size);

+            assert(pSegment);  //TODO

+

+            return 0;    //success

+        }

+

+        pos += size;  //consume payload

+    }

+

+    assert(pos == total);

+

+    pSegment = new Segment(pReader, pos, 0);

+    assert(pSegment);  //TODO

+

+    return 0;  //success (sort of)

+}

+

+

+long long Segment::ParseHeaders()

+{

+    //Outermost (level 0) segment object has been constructed,

+    //and pos designates start of payload.  We need to find the

+    //inner (level 1) elements.

+    long long total, available;

+

+    long hr = m_pReader->Length(&total, &available);

+    assert(hr >= 0);

+    assert(available <= total);

+

+    const long long stop = m_start + m_size;

+    assert(stop <= total);

+    assert(m_pos <= stop);

+

+    bool bQuit = false;

+

+    while ((m_pos < stop) && !bQuit)

+    {

+        long long pos = m_pos;

+

+        long len;

+        long long result = GetUIntLength(m_pReader, pos, len);

+

+        if (result)  //error, or too few available bytes

+            return result;

+

+        if ((pos + len) > stop)

+            return E_FILE_FORMAT_INVALID;

+

+        if ((pos + len) > available)

+            return pos + len;

+

+        const long long idpos = pos;

+        const long long id = ReadUInt(m_pReader, idpos, len);

+

+        if (id < 0)  //error

+            return id;

+

+        pos += len;  //consume ID

+

+        //Read Size

+        result = GetUIntLength(m_pReader, pos, len);

+

+        if (result)  //error, or too few available bytes

+            return result;

+

+        if ((pos + len) > stop)

+            return E_FILE_FORMAT_INVALID;

+

+        if ((pos + len) > available)

+            return pos + len;

+

+        const long long size = ReadUInt(m_pReader, pos, len);

+

+        if (size < 0)

+            return size;

+

+        pos += len;  //consume length of size of element

+

+        //Pos now points to start of payload

+

+        if ((pos + size) > stop)

+            return E_FILE_FORMAT_INVALID;

+

+        //We read EBML elements either in total or nothing at all.

+

+        if ((pos + size) > available)

+            return pos + size;

+

+        if (id == 0x0549A966)  //Segment Info ID

+        {

+            assert(m_pInfo == NULL);

+

+            m_pInfo = new SegmentInfo(this, pos, size);

+            assert(m_pInfo);  //TODO

+        }

+        else if (id == 0x0654AE6B)  //Tracks ID

+        {

+            assert(m_pTracks == NULL);

+

+            m_pTracks = new Tracks(this, pos, size);

+            assert(m_pTracks);  //TODO

+        }

+        else if (id == 0x0C53BB6B)  //Cues ID

+        {

+            if (m_pCues == NULL)

+            {

+                m_pCues = new Cues(this, pos, size);

+                assert(m_pCues);  //TODO

+            }

+        }

+        else if (id == 0x014D9B74)  //SeekHead ID

+        {

+            ParseSeekHead(pos, size);

+        }

+        else if (id == 0x0F43B675)  //Cluster ID

+        {

+            bQuit = true;

+        }

+

+        if (!bQuit)

+            m_pos = pos + size;  //consume payload

+    }

+

+    assert(m_pos <= stop);

+

+    if (m_pInfo == NULL)  //TODO: liberalize this behavior

+        return E_FILE_FORMAT_INVALID;

+

+    if (m_pTracks == NULL)

+        return E_FILE_FORMAT_INVALID;

+

+    return 0;  //success

+}

+

+

+#if 0

+long Segment::ParseCluster(Cluster*& pCluster, long long& pos_) const

+{

+    pCluster = NULL;

+    pos_ = -1;

+

+    const long long stop = m_start + m_size;

+    assert(m_pos <= stop);

+

+    long long pos = m_pos;

+    long long off = -1;

+

+    while (pos < stop)

+    {

+        long len;

+        const long long idpos = pos;

+

+        const long long id = SyncReadUInt(m_pReader, pos, stop, len);

+

+        if (id < 0)  //error

+            return static_cast<long>(id);

+

+        if (id == 0)

+            return E_FILE_FORMAT_INVALID;

+

+        pos += len;  //consume id

+        assert(pos < stop);

+

+        const long long size = SyncReadUInt(m_pReader, pos, stop, len);

+

+        if (size < 0)  //error

+            return static_cast<long>(size);

+

+        pos += len;  //consume size

+        assert(pos <= stop);

+

+        if (size == 0)  //weird

+            continue;

+

+        //pos now points to start of payload

+

+        pos += size;  //consume payload

+        assert(pos <= stop);

+

+        if (id == 0x0F43B675)  //Cluster ID

+        {

+            off = idpos - m_start;  // >= 0 means we found a cluster

+            break;

+        }

+    }

+

+    assert(pos <= stop);

+

+    //Indicate to caller how much of file has been consumed. This is

+    //used later in AddCluster to adjust the current parse position

+    //(the value cached in the segment object itself) to the

+    //file position value just past the cluster we parsed.

+

+    if (off < 0)  //we did not found any more clusters

+    {

+        pos_ = stop;  //pos_ >= 0 here means EOF (cluster is NULL)

+        return 0;     //TODO: confirm this return value

+    }

+

+    //We found a cluster.  Now read something, to ensure that it is

+    //fully loaded in the network cache.

+

+    if (pos >= stop)  //we parsed the entire segment

+    {

+        //We did find a cluster, but it was very last element in the segment.

+        //Our preference is that the loop above runs 1 1/2 times:

+        //the first pass finds the cluster, and the second pass

+        //finds the element the follows the cluster.  In this case, however,

+        //we reached the end of the file without finding another element,

+        //so we didn't actually read anything yet associated with "end of the

+        //cluster".  And we must perform an actual read, in order

+        //to guarantee that all of the data that belongs to this

+        //cluster has been loaded into the network cache.  So instead

+        //of reading the next element that follows the cluster, we

+        //read the last byte of the cluster (which is also the last

+        //byte in the file).

+

+        //Read the last byte of the file. (Reading 0 bytes at pos

+        //might work too -- it would depend on how the reader is

+        //implemented.  Here we take the more conservative approach,

+        //since this makes fewer assumptions about the network

+        //reader abstraction.)

+

+        unsigned char b;

+

+        const int result = m_pReader->Read(pos - 1, 1, &b);

+        assert(result == 0);

+

+        pos_ = stop;

+    }

+    else

+    {

+        long len;

+        const long long idpos = pos;

+

+        const long long id = SyncReadUInt(m_pReader, pos, stop, len);

+

+        if (id < 0)  //error

+            return static_cast<long>(id);

+

+        if (id == 0)

+            return E_BUFFER_NOT_FULL;

+

+        pos += len;  //consume id

+        assert(pos < stop);

+

+        const long long size = SyncReadUInt(m_pReader, pos, stop, len);

+

+        if (size < 0)  //error

+            return static_cast<long>(size);

+

+        pos_ = idpos;

+    }

+

+    //We found a cluster, and it has been completely loaded into the

+    //network cache.  (We can guarantee this because we actually read

+    //the EBML tag that follows the cluster, or, if we reached EOF,

+    //because we actually read the last byte of the cluster).

+

+    Segment* const this_ = const_cast<Segment*>(this);

+

+    pCluster = Cluster::Parse(this_, m_clusterCount, off);

+    assert(pCluster);

+    assert(pCluster->m_index == m_clusterCount);

+

+    return 0;

+}

+

+

+bool Segment::AddCluster(Cluster* pCluster, long long pos)

+{

+    assert(pos >= m_start);

+

+    const long long stop = m_start + m_size;

+    assert(pos <= stop);

+

+    if (pCluster)

+    {

+        AppendCluster(pCluster);

+        assert(m_clusters);

+        assert(m_clusterSize > pCluster->m_index);

+        assert(m_clusters[pCluster->m_index] == pCluster);

+    }

+

+    m_pos = pos;  //m_pos >= stop is now we know we have all clusters

+

+    return (pos >= stop);

+}

+#endif

+

+

+long Segment::LoadCluster()

+{

+    const long long stop = m_start + m_size;

+

+    while (m_pos < stop)

+    {

+        long long pos = m_pos;

+

+        long len;

+

+        long long result = GetUIntLength(m_pReader, pos, len);

+

+        if (result < 0)  //error

+            return static_cast<long>(result);

+

+        if ((pos + len) > stop)

+            return E_FILE_FORMAT_INVALID;

+

+        const long long idpos = pos;

+        const long long id = ReadUInt(m_pReader, idpos, len);

+

+        if (id < 0)  //error

+            return static_cast<long>(id);

+

+        pos += len;  //consume ID

+

+        //Read Size

+        result = GetUIntLength(m_pReader, pos, len);

+

+        if (result < 0)  //error

+            return static_cast<long>(result);

+

+        if ((pos + len) > stop)

+            return E_FILE_FORMAT_INVALID;

+

+        const long long size = ReadUInt(m_pReader, pos, len);

+

+        if (size < 0)  //error

+            return static_cast<long>(size);

+

+        pos += len;  //consume length of size of element

+

+        if (size == 0)  //weird

+        {

+            m_pos = pos;

+            continue;

+        }

+

+        //Pos now points to start of payload

+

+        if ((pos + size) > stop)

+            return E_FILE_FORMAT_INVALID;

+

+        if (id == 0x0C53BB6B)  //Cues ID

+        {

+            if (m_pCues == NULL)

+            {

+                m_pCues = new Cues(this, pos, size);

+                assert(m_pCues);  //TODO

+            }

+

+            m_pos = pos + size;  //consume payload

+            continue;

+        }

+

+        if (id != 0x0F43B675)  //Cluster ID

+        {

+            m_pos = pos + size;  //consume payload

+            continue;

+        }

+

+        const long idx = m_clusterCount;

+        const long long idoff = idpos - m_start;

+

+        if (m_clusterPreloadCount > 0)

+        {

+            assert(idx < m_clusterSize);

+

+            Cluster* const pCluster = m_clusters[idx];

+            assert(pCluster);

+            assert(pCluster->m_index < 0);

+

+            const long long off_ = pCluster->m_pos;

+            assert(off_);

+

+            const long long off = off_ * ((off_ >= 0) ? 1 : -1);

+            assert(idoff <= off);

+

+            if (idoff == off)  //cluster has been preloaded already

+            {

+                pCluster->m_index = idx;

+                ++m_clusterCount;

+                --m_clusterPreloadCount;

+

+                m_pos = pos + size;  //consume payload

+                break;

+            }

+        }

+

+        Cluster* const pCluster = Cluster::Parse(this, idx, idoff);

+        assert(pCluster);

+        assert(pCluster->m_index == idx);

+

+        AppendCluster(pCluster);

+        assert(m_clusters);

+        assert(idx < m_clusterSize);

+        assert(m_clusters[idx] == pCluster);

+

+        m_pos = pos + size;  //consume payload

+        break;

+    }

+

+    assert(m_pos <= stop);

+    return 0;

+}

+

+

+void Segment::AppendCluster(Cluster* pCluster)

+{

+    assert(pCluster);

+    assert(pCluster->m_index >= 0);

+

+    const long count = m_clusterCount + m_clusterPreloadCount;

+

+    long& size = m_clusterSize;

+    assert(size >= count);

+

+    const long idx = pCluster->m_index;

+    assert(idx == m_clusterCount);

+

+    if (count >= size)

+    {

+        long n;

+

+        if (size > 0)

+            n = 2 * size;

+        else if (m_pInfo == 0)

+            n = 2048;

+        else

+        {

+            const long long ns = m_pInfo->GetDuration();

+

+            if (ns <= 0)

+                n = 2048;

+            else

+            {

+                const long long sec = (ns + 999999999LL) / 1000000000LL;

+                n = static_cast<long>(sec);

+            }

+        }

+

+        Cluster** const qq = new Cluster*[n];

+        Cluster** q = qq;

+

+        Cluster** p = m_clusters;

+        Cluster** const pp = p + count;

+

+        while (p != pp)

+            *q++ = *p++;

+

+        delete[] m_clusters;

+

+        m_clusters = qq;

+        size = n;

+    }

+

+    if (m_clusterPreloadCount > 0)

+    {

+        assert(m_clusters);

+

+        Cluster** const p = m_clusters + m_clusterCount;

+        assert(*p);

+        assert((*p)->m_index < 0);

+

+        Cluster** q = p + m_clusterPreloadCount;

+        assert(q < (m_clusters + size));

+

+        for (;;)

+        {

+            Cluster** const qq = q - 1;

+            assert((*qq)->m_index < 0);

+

+            *q = *qq;

+            q = qq;

+

+            if (q == p)

+                break;

+        }

+    }

+

+    m_clusters[idx] = pCluster;

+    ++m_clusterCount;

+}

+

+

+void Segment::PreloadCluster(Cluster* pCluster, ptrdiff_t idx)

+{

+    assert(pCluster);

+    assert(pCluster->m_index < 0);

+    assert(idx >= m_clusterCount);

+

+    const long count = m_clusterCount + m_clusterPreloadCount;

+

+    long& size = m_clusterSize;

+    assert(size >= count);

+

+    if (count >= size)

+    {

+        long n;

+

+        if (size > 0)

+            n = 2 * size;

+        else if (m_pInfo == 0)

+            n = 2048;

+        else

+        {

+            const long long ns = m_pInfo->GetDuration();

+

+            if (ns <= 0)

+                n = 2048;

+            else

+            {

+                const long long sec = (ns + 999999999LL) / 1000000000LL;

+                n = static_cast<long>(sec);

+            }

+        }

+

+        Cluster** const qq = new Cluster*[n];

+        Cluster** q = qq;

+

+        Cluster** p = m_clusters;

+        Cluster** const pp = p + count;

+

+        while (p != pp)

+            *q++ = *p++;

+

+        delete[] m_clusters;

+

+        m_clusters = qq;

+        size = n;

+    }

+

+    assert(m_clusters);

+

+    Cluster** const p = m_clusters + idx;

+

+    Cluster** q = m_clusters + count;

+    assert(q >= p);

+    assert(q < (m_clusters + size));

+

+    while (q > p)

+    {

+        Cluster** const qq = q - 1;

+        assert((*qq)->m_index < 0);

+

+        *q = *qq;

+        q = qq;

+    }

+

+    m_clusters[idx] = pCluster;

+    ++m_clusterPreloadCount;

+}

+

+

+long Segment::Load()

+{

+    assert(m_clusters == NULL);

+    assert(m_clusterSize == 0);

+    assert(m_clusterCount == 0);

+

+    //Outermost (level 0) segment object has been constructed,

+    //and pos designates start of payload.  We need to find the

+    //inner (level 1) elements.

+    const long long stop = m_start + m_size;

+

+#ifdef _DEBUG  //TODO: this is really Microsoft-specific

+    {

+        long long total, available;

+

+        long hr = m_pReader->Length(&total, &available);

+        assert(hr >= 0);

+        assert(available >= total);

+        assert(stop <= total);

+    }

+#endif

+

+    while (m_pos < stop)

+    {

+        long long pos = m_pos;

+

+        long len;

+

+        long long result = GetUIntLength(m_pReader, pos, len);

+

+        if (result < 0)  //error

+            return static_cast<long>(result);

+

+        if ((pos + len) > stop)

+            return E_FILE_FORMAT_INVALID;

+

+        const long long idpos = pos;

+        const long long id = ReadUInt(m_pReader, idpos, len);

+

+        if (id < 0)  //error

+            return static_cast<long>(id);

+

+        pos += len;  //consume ID

+

+        //Read Size

+        result = GetUIntLength(m_pReader, pos, len);

+

+        if (result < 0)  //error

+            return static_cast<long>(result);

+

+        if ((pos + len) > stop)

+            return E_FILE_FORMAT_INVALID;

+

+        const long long size = ReadUInt(m_pReader, pos, len);

+

+        if (size < 0)  //error

+            return static_cast<long>(size);

+

+        pos += len;  //consume length of size of element

+

+        //Pos now points to start of payload

+

+        if ((pos + size) > stop)

+            return E_FILE_FORMAT_INVALID;

+

+        if (id == 0x0F43B675)  //Cluster ID

+        {

+            const long idx = m_clusterCount;

+            const long long off = idpos - m_start;

+

+            Cluster* const pCluster = Cluster::Parse(this, idx, off);

+            assert(pCluster);

+            assert(pCluster->m_index == idx);

+

+            AppendCluster(pCluster);

+            assert(m_clusters);

+            assert(m_clusterSize > idx);

+            assert(m_clusters[idx] == pCluster);

+        }

+        else if (id == 0x0C53BB6B)  //Cues ID

+        {

+            assert(m_pCues == NULL);

+

+            m_pCues = new Cues(this, pos, size);

+            assert(m_pCues);  //TODO

+        }

+        else if (id == 0x0549A966)  //SegmentInfo ID

+        {

+            assert(m_pInfo == NULL);

+

+            m_pInfo = new  SegmentInfo(this, pos, size);

+            assert(m_pInfo);

+        }

+        else if (id == 0x0654AE6B)  //Tracks ID

+        {

+            assert(m_pTracks == NULL);

+

+            m_pTracks = new Tracks(this, pos, size);

+            assert(m_pTracks);  //TODO

+        }

+

+        m_pos = pos + size;  //consume payload

+    }

+

+    assert(m_pos >= stop);

+

+    if (m_pInfo == NULL)

+        return E_FILE_FORMAT_INVALID;  //TODO: ignore this case?

+

+    if (m_pTracks == NULL)

+        return E_FILE_FORMAT_INVALID;

+

+    if (m_clusters == NULL)  //TODO: ignore this case?

+        return E_FILE_FORMAT_INVALID;

+

+    //TODO: decide whether we require Cues element

+    //if (m_pCues == NULL)

+    //   return E_FILE_FORMAT_INVALID;

+

+    return 0;

+}

+

+

+void Segment::ParseSeekHead(long long start, long long size_)

+{

+    long long pos = start;

+    const long long stop = start + size_;

+

+    while (pos < stop)

+    {

+        long len;

+

+        const long long id = ReadUInt(m_pReader, pos, len);

+        assert(id >= 0);  //TODO

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume ID

+

+        const long long size = ReadUInt(m_pReader, pos, len);

+        assert(size >= 0);

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume Size field

+        assert((pos + size) <= stop);

+

+        if (id == 0x0DBB)  //SeekEntry ID

+            ParseSeekEntry(pos, size);

+

+        pos += size;  //consume payload

+        assert(pos <= stop);

+    }

+

+    assert(pos == stop);

+}

+

+

+void Segment::ParseCues(long long off)

+{

+    if (m_pCues)

+        return;

+

+    //odbgstream os;

+    //os << "Segment::ParseCues (begin)" << endl;

+

+    long long pos = m_start + off;

+    const long long stop = m_start + m_size;

+

+    long len;

+

+    long long result = GetUIntLength(m_pReader, pos, len);

+    assert(result == 0);

+    assert((pos + len) <= stop);

+

+    const long long idpos = pos;

+

+    const long long id = ReadUInt(m_pReader, idpos, len);

+    assert(id == 0x0C53BB6B);  //Cues ID

+

+    pos += len;  //consume ID

+    assert(pos < stop);

+

+    //Read Size

+

+    result = GetUIntLength(m_pReader, pos, len);

+    assert(result == 0);

+    assert((pos + len) <= stop);

+

+    const long long size = ReadUInt(m_pReader, pos, len);

+    assert(size >= 0);

+

+    pos += len;  //consume length of size of element

+    assert((pos + size) <= stop);

+

+    //Pos now points to start of payload

+

+    m_pCues = new Cues(this, pos, size);

+    assert(m_pCues);  //TODO

+

+    //os << "Segment::ParseCues (end)" << endl;

+}

+

+

+void Segment::ParseSeekEntry(

+   long long start,

+   long long size_)

+{

+    long long pos = start;

+

+    const long long stop = start + size_;

+

+    long len;

+

+    const long long seekIdId = ReadUInt(m_pReader, pos, len);

+    //seekIdId;

+    assert(seekIdId == 0x13AB);  //SeekID ID

+    assert((pos + len) <= stop);

+

+    pos += len;  //consume id

+

+    const long long seekIdSize = ReadUInt(m_pReader, pos, len);

+    assert(seekIdSize >= 0);

+    assert((pos + len) <= stop);

+

+    pos += len;  //consume size

+

+    const long long seekId = ReadUInt(m_pReader, pos, len);  //payload

+    assert(seekId >= 0);

+    assert(len == seekIdSize);

+    assert((pos + len) <= stop);

+

+    pos += seekIdSize;  //consume payload

+

+    const long long seekPosId = ReadUInt(m_pReader, pos, len);

+    //seekPosId;

+    assert(seekPosId == 0x13AC);  //SeekPos ID

+    assert((pos + len) <= stop);

+

+    pos += len;  //consume id

+

+    const long long seekPosSize = ReadUInt(m_pReader, pos, len);

+    assert(seekPosSize >= 0);

+    assert((pos + len) <= stop);

+

+    pos += len;  //consume size

+    assert((pos + seekPosSize) <= stop);

+

+    const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize);

+    assert(seekOff >= 0);

+    assert(seekOff < m_size);

+

+    pos += seekPosSize;  //consume payload

+    assert(pos == stop);

+

+    const long long seekPos = m_start + seekOff;

+    assert(seekPos < (m_start + m_size));

+

+    if (seekId == 0x0C53BB6B)  //Cues ID

+        ParseCues(seekOff);

+}

+

+

+Cues::Cues(Segment* pSegment, long long start_, long long size_) :

+    m_pSegment(pSegment),

+    m_start(start_),

+    m_size(size_),

+    m_cue_points(NULL),

+    m_count(0),

+    m_preload_count(0),

+    m_pos(start_)

+{

+}

+

+

+Cues::~Cues()

+{

+    const size_t n = m_count + m_preload_count;

+

+    CuePoint** p = m_cue_points;

+    CuePoint** const q = p + n;

+

+    while (p != q)

+    {

+        CuePoint* const pCP = *p++;

+        assert(pCP);

+

+        delete pCP;

+    }

+

+    delete[] m_cue_points;

+}

+

+

+void Cues::Init() const

+{

+    if (m_cue_points)

+        return;

+

+    assert(m_count == 0);

+    assert(m_preload_count == 0);

+

+    IMkvReader* const pReader = m_pSegment->m_pReader;

+

+    const long long stop = m_start + m_size;

+    long long pos = m_start;

+

+    size_t cue_points_size = 0;

+

+    while (pos < stop)

+    {

+        const long long idpos = pos;

+

+        long len;

+

+        const long long id = ReadUInt(pReader, pos, len);

+        assert(id >= 0);  //TODO

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume ID

+

+        const long long size = ReadUInt(pReader, pos, len);

+        assert(size >= 0);

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume Size field

+        assert((pos + size) <= stop);

+

+        if (id == 0x3B)  //CuePoint ID

+            PreloadCuePoint(cue_points_size, idpos);

+

+        pos += size;  //consume payload

+        assert(pos <= stop);

+    }

+}

+

+

+void Cues::PreloadCuePoint(

+    size_t& cue_points_size,

+    long long pos) const

+{

+    assert(m_count == 0);

+

+    if (m_preload_count >= cue_points_size)

+    {

+        size_t n;

+

+        if (cue_points_size > 0)

+            n = static_cast<size_t>(2 * cue_points_size);

+        else

+        {

+            const SegmentInfo* const pInfo = m_pSegment->GetInfo();

+

+            if (pInfo == NULL)

+                n = 2048;

+            else

+            {

+                const long long ns = pInfo->GetDuration();

+

+                if (ns <= 0)

+                    n = 2048;

+                else

+                {

+                    const long long sec = (ns + 999999999LL) / 1000000000LL;

+                    n = static_cast<size_t>(sec);

+                }

+            }

+        }

+

+        CuePoint** const qq = new CuePoint*[n];

+        CuePoint** q = qq;  //beginning of target

+

+        CuePoint** p = m_cue_points;                //beginning of source

+        CuePoint** const pp = p + m_preload_count;  //end of source

+

+        while (p != pp)

+            *q++ = *p++;

+

+        delete[] m_cue_points;

+

+        m_cue_points = qq;

+        cue_points_size = n;

+    }

+

+    CuePoint* const pCP = new CuePoint(m_preload_count, pos);

+    m_cue_points[m_preload_count++] = pCP;

+}

+

+

+bool Cues::LoadCuePoint() const

+{

+    //odbgstream os;

+    //os << "Cues::LoadCuePoint" << endl;

+

+    const long long stop = m_start + m_size;

+

+    if (m_pos >= stop)

+        return false;  //nothing else to do

+

+    Init();

+

+    IMkvReader* const pReader = m_pSegment->m_pReader;

+

+    while (m_pos < stop)

+    {

+        const long long idpos = m_pos;

+

+        long len;

+

+        const long long id = ReadUInt(pReader, m_pos, len);

+        assert(id >= 0);  //TODO

+        assert((m_pos + len) <= stop);

+

+        m_pos += len;  //consume ID

+

+        const long long size = ReadUInt(pReader, m_pos, len);

+        assert(size >= 0);

+        assert((m_pos + len) <= stop);

+

+        m_pos += len;  //consume Size field

+        assert((m_pos + size) <= stop);

+

+        if (id != 0x3B)  //CuePoint ID

+        {

+            m_pos += size;  //consume payload

+            assert(m_pos <= stop);

+

+            continue;

+        }

+

+        assert(m_preload_count > 0);

+

+        CuePoint* const pCP = m_cue_points[m_count];

+        assert(pCP);

+        assert((pCP->GetTimeCode() >= 0) || (-pCP->GetTimeCode() == idpos));

+

+        pCP->Load(pReader);

+        ++m_count;

+        --m_preload_count;

+

+        m_pos += size;  //consume payload

+        assert(m_pos <= stop);

+

+        break;

+    }

+

+    return (m_pos < stop);

+}

+

+

+bool Cues::Find(

+    long long time_ns,

+    const Track* pTrack,

+    const CuePoint*& pCP,

+    const CuePoint::TrackPosition*& pTP) const

+{

+    assert(time_ns >= 0);

+    assert(pTrack);

+

+    LoadCuePoint();

+

+    assert(m_cue_points);

+    assert(m_count > 0);

+

+    CuePoint** const ii = m_cue_points;

+    CuePoint** i = ii;

+

+    CuePoint** const jj = ii + m_count + m_preload_count;

+    CuePoint** j = jj;

+

+    pCP = *i;

+    assert(pCP);

+

+    if (time_ns <= pCP->GetTime(m_pSegment))

+    {

+        pTP = pCP->Find(pTrack);

+        return (pTP != NULL);

+    }

+

+    IMkvReader* const pReader = m_pSegment->m_pReader;

+

+    while (i < j)

+    {

+        //INVARIANT:

+        //[ii, i) <= time_ns

+        //[i, j)  ?

+        //[j, jj) > time_ns

+

+        CuePoint** const k = i + (j - i) / 2;

+        assert(k < jj);

+

+        CuePoint* const pCP = *k;

+        assert(pCP);

+

+        pCP->Load(pReader);

+

+        const long long t = pCP->GetTime(m_pSegment);

+

+        if (t <= time_ns)

+            i = k + 1;

+        else

+            j = k;

+

+        assert(i <= j);

+    }

+

+    assert(i == j);

+    assert(i <= jj);

+    assert(i > ii);

+

+    pCP = *--i;

+    assert(pCP);

+    assert(pCP->GetTime(m_pSegment) <= time_ns);

+

+    //TODO: here and elsewhere, it's probably not correct to search

+    //for the cue point with this time, and then search for a matching

+    //track.  In principle, the matching track could be on some earlier

+    //cue point, and with our current algorithm, we'd miss it.  To make

+    //this bullet-proof, we'd need to create a secondary structure,

+    //with a list of cue points that apply to a track, and then search

+    //that track-based structure for a matching cue point.

+

+    pTP = pCP->Find(pTrack);

+    return (pTP != NULL);

+}

+

+

+#if 0

+bool Cues::FindNext(

+    long long time_ns,

+    const Track* pTrack,

+    const CuePoint*& pCP,

+    const CuePoint::TrackPosition*& pTP) const

+{

+    pCP = 0;

+    pTP = 0;

+

+    if (m_count == 0)

+        return false;

+

+    assert(m_cue_points);

+

+    const CuePoint* const* const ii = m_cue_points;

+    const CuePoint* const* i = ii;

+

+    const CuePoint* const* const jj = ii + m_count;

+    const CuePoint* const* j = jj;

+

+    while (i < j)

+    {

+        //INVARIANT:

+        //[ii, i) <= time_ns

+        //[i, j)  ?

+        //[j, jj) > time_ns

+

+        const CuePoint* const* const k = i + (j - i) / 2;

+        assert(k < jj);

+

+        pCP = *k;

+        assert(pCP);

+

+        const long long t = pCP->GetTime(m_pSegment);

+

+        if (t <= time_ns)

+            i = k + 1;

+        else

+            j = k;

+

+        assert(i <= j);

+    }

+

+    assert(i == j);

+    assert(i <= jj);

+

+    if (i >= jj)  //time_ns is greater than max cue point

+        return false;

+

+    pCP = *i;

+    assert(pCP);

+    assert(pCP->GetTime(m_pSegment) > time_ns);

+

+    pTP = pCP->Find(pTrack);

+    return (pTP != NULL);

+}

+#endif

+

+

+const CuePoint* Cues::GetFirst() const

+{

+    LoadCuePoint();  //init cues

+

+    const size_t count = m_count + m_preload_count;

+

+    if (count == 0)  //weird

+        return NULL;

+

+    CuePoint* const* const pp = m_cue_points;

+    assert(pp);

+

+    CuePoint* const pCP = pp[0];

+    assert(pCP);

+    assert(pCP->GetTimeCode() >= 0);

+

+    return pCP;

+}

+

+

+const CuePoint* Cues::GetLast() const

+{

+    LoadCuePoint();  //init cues

+

+    const size_t count = m_count + m_preload_count;

+

+    if (count == 0)  //weird

+        return NULL;

+

+    const size_t index = count - 1;

+

+    CuePoint* const* const pp = m_cue_points;

+    assert(pp);

+

+    CuePoint* const pCP = pp[index];

+    assert(pCP);

+

+    pCP->Load(m_pSegment->m_pReader);

+    assert(pCP->GetTimeCode() >= 0);

+

+    return pCP;

+}

+

+

+const CuePoint* Cues::GetNext(const CuePoint* pCurr) const

+{

+    if (pCurr == NULL)

+        return NULL;

+

+    assert(pCurr->GetTimeCode() >= 0);

+    assert(m_cue_points);

+    assert(m_count >= 1);

+

+    const size_t count = m_count + m_preload_count;

+

+    size_t index = pCurr->m_index;

+    assert(index < count);

+

+    CuePoint* const* const pp = m_cue_points;

+    assert(pp);

+    assert(pp[index] == pCurr);

+

+    ++index;

+

+    if (index >= count)

+        return NULL;

+

+    CuePoint* const pNext = pp[index];

+    assert(pNext);

+

+    pNext->Load(m_pSegment->m_pReader);

+

+    return pNext;

+}

+

+

+const BlockEntry* Cues::GetBlock(

+    const CuePoint* pCP,

+    const CuePoint::TrackPosition* pTP) const

+{

+    if (pCP == NULL)

+        return NULL;

+

+    if (pTP == NULL)

+        return NULL;

+

+    return m_pSegment->GetBlock(*pCP, *pTP);

+}

+

+

+const BlockEntry* Segment::GetBlock(

+    const CuePoint& cp,

+    const CuePoint::TrackPosition& tp)

+{

+    Cluster** const ii = m_clusters;

+    Cluster** i = ii;

+

+    const long count = m_clusterCount + m_clusterPreloadCount;

+

+    Cluster** const jj = ii + count;

+    Cluster** j = jj;

+

+    while (i < j)

+    {

+        //INVARIANT:

+        //[ii, i) < pTP->m_pos

+        //[i, j) ?

+        //[j, jj)  > pTP->m_pos

+

+        Cluster** const k = i + (j - i) / 2;

+        assert(k < jj);

+

+        Cluster* const pCluster = *k;

+        assert(pCluster);

+

+        const long long pos_ = pCluster->m_pos;

+        assert(pos_);

+

+        const long long pos = pos_ * ((pos_ < 0) ? -1 : 1);

+

+        if (pos < tp.m_pos)

+            i = k + 1;

+        else if (pos > tp.m_pos)

+            j = k;

+        else

+            return pCluster->GetEntry(cp, tp);

+    }

+

+    assert(i == j);

+

+    Cluster* const pCluster = Cluster::Parse(this, -1, tp.m_pos);

+    const ptrdiff_t idx = i - m_clusters;

+

+    PreloadCluster(pCluster, idx);

+    assert(m_clusters);

+    assert(m_clusterPreloadCount > 0);

+    assert(m_clusters[idx] == pCluster);

+

+    return pCluster->GetEntry(cp, tp);

+}

+

+

+

+CuePoint::CuePoint(size_t idx, long long pos) :

+    m_index(idx),

+    m_timecode(-1 * pos),

+    m_track_positions(NULL),

+    m_track_positions_count(0)

+{

+    assert(pos > 0);

+}

+

+

+CuePoint::~CuePoint()

+{

+    delete[] m_track_positions;

+}

+

+

+void CuePoint::Load(IMkvReader* pReader)

+{

+    //odbgstream os;

+    //os << "CuePoint::Load(begin): timecode=" << m_timecode << endl;

+

+    if (m_timecode >= 0)  //already loaded

+        return;

+

+    assert(m_track_positions == NULL);

+    assert(m_track_positions_count == 0);

+

+    long long pos_ = -m_timecode;

+

+    long long stop;

+

+    {

+        long len;

+

+        const long long id = ReadUInt(pReader, pos_, len);

+        assert(id == 0x3B);  //CuePoint ID

+        //assert((pos + len) <= stop);

+

+        pos_ += len;  //consume ID

+

+        const long long size = ReadUInt(pReader, pos_, len);

+        assert(size >= 0);

+        //assert((pos + len) <= stop);

+

+        pos_ += len;  //consume Size field

+        //assert((pos + size) <= stop);

+

+        //pos_ now points to start of payload

+

+        stop = pos_ + size;

+    }

+

+    long long pos = pos_;

+

+    //First count number of track positions

+

+    while (pos < stop)

+    {

+        long len;

+

+        const long long id = ReadUInt(pReader, pos, len);

+        assert(id >= 0);  //TODO

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume ID

+

+        const long long size = ReadUInt(pReader, pos, len);

+        assert(size >= 0);

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume Size field

+        assert((pos + size) <= stop);

+

+        if (id == 0x33)  //CueTime ID

+            m_timecode = UnserializeUInt(pReader, pos, size);

+

+        else if (id == 0x37) //CueTrackPosition(s) ID

+            ++m_track_positions_count;

+

+        pos += size;  //consume payload

+        assert(pos <= stop);

+    }

+

+    assert(m_timecode >= 0);

+    assert(m_track_positions_count > 0);

+

+    //os << "CuePoint::Load(cont'd): idpos=" << idpos

+    //   << " timecode=" << m_timecode

+    //   << endl;

+

+    m_track_positions = new TrackPosition[m_track_positions_count];

+

+    //Now parse track positions

+

+    TrackPosition* p = m_track_positions;

+    pos = pos_;

+

+    while (pos < stop)

+    {

+        long len;

+

+        const long long id = ReadUInt(pReader, pos, len);

+        assert(id >= 0);  //TODO

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume ID

+

+        const long long size = ReadUInt(pReader, pos, len);

+        assert(size >= 0);

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume Size field

+        assert((pos + size) <= stop);

+

+        if (id == 0x37) //CueTrackPosition(s) ID

+        {

+            TrackPosition& tp = *p++;

+            tp.Parse(pReader, pos, size);

+        }

+

+        pos += size;  //consume payload

+        assert(pos <= stop);

+    }

+

+    assert(size_t(p - m_track_positions) == m_track_positions_count);

+}

+

+

+

+void CuePoint::TrackPosition::Parse(

+    IMkvReader* pReader,

+    long long start_,

+    long long size_)

+{

+    const long long stop = start_ + size_;

+    long long pos = start_;

+

+    m_track = -1;

+    m_pos = -1;

+    m_block = 1;  //default

+

+    while (pos < stop)

+    {

+        long len;

+

+        const long long id = ReadUInt(pReader, pos, len);

+        assert(id >= 0);  //TODO

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume ID

+

+        const long long size = ReadUInt(pReader, pos, len);

+        assert(size >= 0);

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume Size field

+        assert((pos + size) <= stop);

+

+        if (id == 0x77)  //CueTrack ID

+            m_track = UnserializeUInt(pReader, pos, size);

+

+        else if (id == 0x71)  //CueClusterPos ID

+            m_pos = UnserializeUInt(pReader, pos, size);

+

+        else if (id == 0x1378)  //CueBlockNumber

+            m_block = UnserializeUInt(pReader, pos, size);

+

+        pos += size;  //consume payload

+        assert(pos <= stop);

+    }

+

+    assert(m_pos >= 0);

+    //assert(m_track > 0);

+    //assert(m_block > 0);

+}

+

+

+const CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const

+{

+    assert(pTrack);

+

+    const long long n = pTrack->GetNumber();

+

+    const TrackPosition* i = m_track_positions;

+    const TrackPosition* const j = i + m_track_positions_count;

+

+    while (i != j)

+    {

+        const TrackPosition& p = *i++;

+

+        if (p.m_track == n)

+            return &p;

+    }

+

+    return NULL;  //no matching track number found

+}

+

+

+long long CuePoint::GetTimeCode() const

+{

+    return m_timecode;

+}

+

+long long CuePoint::GetTime(Segment* pSegment) const

+{

+    assert(pSegment);

+    assert(m_timecode >= 0);

+

+    const SegmentInfo* const pInfo = pSegment->GetInfo();

+    assert(pInfo);

+

+    const long long scale = pInfo->GetTimeCodeScale();

+    assert(scale >= 1);

+

+    const long long time = scale * m_timecode;

+

+    return time;

+}

+

+

+long long Segment::Unparsed() const

+{

+    const long long stop = m_start + m_size;

+

+    const long long result = stop - m_pos;

+    assert(result >= 0);

+

+    return result;

+}

+

+

+Cluster* Segment::GetFirst()

+{

+    if ((m_clusters == NULL) || (m_clusterCount <= 0))

+       return &m_eos;

+

+    Cluster* const pCluster = m_clusters[0];

+    assert(pCluster);

+

+    return pCluster;

+}

+

+

+Cluster* Segment::GetLast()

+{

+    if ((m_clusters == NULL) || (m_clusterCount <= 0))

+        return &m_eos;

+

+    const long idx = m_clusterCount - 1;

+

+    Cluster* const pCluster = m_clusters[idx];

+    assert(pCluster);

+

+    return pCluster;

+}

+

+

+unsigned long Segment::GetCount() const

+{

+    return m_clusterCount;

+}

+

+

+Cluster* Segment::GetNext(const Cluster* pCurr)

+{

+    assert(pCurr);

+    assert(pCurr != &m_eos);

+    assert(m_clusters);

+

+    long idx =  pCurr->m_index;

+

+    if (idx >= 0)

+    {

+        assert(m_clusterCount > 0);

+        assert(idx < m_clusterCount);

+        assert(pCurr == m_clusters[idx]);

+

+        ++idx;

+

+        if (idx >= m_clusterCount)

+            return &m_eos;  //caller will LoadCluster as desired

+

+        Cluster* const pNext = m_clusters[idx];

+        assert(pNext);

+        assert(pNext->m_index >= 0);

+        assert(pNext->m_index == idx);

+

+        return pNext;

+    }

+

+    assert(m_clusterPreloadCount > 0);

+

+    const long long off_ = pCurr->m_pos;

+    const long long off = off_ * ((off_ < 0) ? -1 : 1);

+

+    long long pos = m_start + off;

+    const long long stop = m_start + m_size;  //end of segment

+

+    {

+        long len;

+

+        long long result = GetUIntLength(m_pReader, pos, len);

+        assert(result == 0);  //TODO

+        assert((pos + len) <= stop);  //TODO

+

+        const long long id = ReadUInt(m_pReader, pos, len);

+        assert(id == 0x0F43B675);  //Cluster ID   //TODO

+

+        pos += len;  //consume ID

+

+        //Read Size

+        result = GetUIntLength(m_pReader, pos, len);

+        assert(result == 0);  //TODO

+        assert((pos + len) <= stop);  //TODO

+

+        const long long size = ReadUInt(m_pReader, pos, len);

+        assert(size > 0);  //TODO

+        assert((pCurr->m_size <= 0) || (pCurr->m_size == size));

+

+        pos += len;  //consume length of size of element

+        assert((pos + size) <= stop);  //TODO

+

+        //Pos now points to start of payload

+

+        pos += size;  //consume payload

+    }

+

+    long long off_next = 0;

+

+    while (pos < stop)

+    {

+        long len;

+

+        long long result = GetUIntLength(m_pReader, pos, len);

+        assert(result == 0);  //TODO

+        assert((pos + len) <= stop);  //TODO

+

+        const long long idpos = pos;  //pos of next (potential) cluster

+

+        const long long id = ReadUInt(m_pReader, idpos, len);

+        assert(id > 0);  //TODO

+

+        pos += len;  //consume ID

+

+        //Read Size

+        result = GetUIntLength(m_pReader, pos, len);

+        assert(result == 0);  //TODO

+        assert((pos + len) <= stop);  //TODO

+

+        const long long size = ReadUInt(m_pReader, pos, len);

+        assert(size >= 0);  //TODO

+

+        pos += len;  //consume length of size of element

+        assert((pos + size) <= stop);  //TODO

+

+        //Pos now points to start of payload

+

+        if (size == 0)  //weird

+            continue;

+

+        if (id == 0x0F43B675)  //Cluster ID

+        {

+            off_next = idpos - m_start;

+            break;

+        }

+

+        pos += size;  //consume payload

+    }

+

+    if (off_next <= 0)

+        return 0;

+

+    Cluster** const ii = m_clusters + m_clusterCount;

+    Cluster** i = ii;

+

+    Cluster** const jj = ii + m_clusterPreloadCount;

+    Cluster** j = jj;

+

+    while (i < j)

+    {

+        //INVARIANT:

+        //[0, i) < pos_next

+        //[i, j) ?

+        //[j, jj)  > pos_next

+

+        Cluster** const k = i + (j - i) / 2;

+        assert(k < jj);

+

+        Cluster* const pNext = *k;

+        assert(pNext);

+        assert(pNext->m_index < 0);

+

+        const long long pos_ = pNext->m_pos;

+        assert(pos_);

+

+        pos = pos_ * ((pos_ < 0) ? -1 : 1);

+

+        if (pos < off_next)

+            i = k + 1;

+        else if (pos > off_next)

+            j = k;

+        else

+            return pNext;

+    }

+

+    assert(i == j);

+

+    Cluster* const pNext = Cluster::Parse(this, -1, off_next);

+    const ptrdiff_t idx_next = i - m_clusters;  //insertion position

+

+    PreloadCluster(pNext, idx_next);

+    assert(m_clusters);

+    assert(idx_next < m_clusterSize);

+    assert(m_clusters[idx_next] == pNext);

+

+    return pNext;

+}

+

+

+Cluster* Segment::FindCluster(long long time_ns)

+{

+    if ((m_clusters == NULL) || (m_clusterCount <= 0))

+        return &m_eos;

+

+    {

+        Cluster* const pCluster = m_clusters[0];

+        assert(pCluster);

+        assert(pCluster->m_index == 0);

+

+        if (time_ns <= pCluster->GetTime())

+            return pCluster;

+    }

+

+    //Binary search of cluster array

+

+    long i = 0;

+    long j = m_clusterCount;

+

+    while (i < j)

+    {

+        //INVARIANT:

+        //[0, i) <= time_ns

+        //[i, j) ?

+        //[j, m_clusterCount)  > time_ns

+

+        const long k = i + (j - i) / 2;

+        assert(k < m_clusterCount);

+

+        Cluster* const pCluster = m_clusters[k];

+        assert(pCluster);

+        assert(pCluster->m_index == k);

+

+        const long long t = pCluster->GetTime();

+

+        if (t <= time_ns)

+            i = k + 1;

+        else

+            j = k;

+

+        assert(i <= j);

+    }

+

+    assert(i == j);

+    assert(i > 0);

+    assert(i <= m_clusterCount);

+

+    const long k = i - 1;

+

+    Cluster* const pCluster = m_clusters[k];

+    assert(pCluster);

+    assert(pCluster->m_index == k);

+    assert(pCluster->GetTime() <= time_ns);

+

+    return pCluster;

+}

+

+

+const BlockEntry* Segment::Seek(

+    long long time_ns,

+    const Track* pTrack)

+{

+    assert(pTrack);

+

+    if ((m_clusters == NULL) || (m_clusterCount <= 0))

+        return pTrack->GetEOS();

+

+    Cluster** const i = m_clusters;

+    assert(i);

+

+    {

+        Cluster* const pCluster = *i;

+        assert(pCluster);

+        assert(pCluster->m_index == 0);  //m_clusterCount > 0

+        assert(pCluster->m_pSegment == this);

+

+        if (time_ns <= pCluster->GetTime())

+            return pCluster->GetEntry(pTrack);

+    }

+

+    Cluster** const j = i + m_clusterCount;

+

+    if (pTrack->GetType() == 2)  //audio

+    {

+        //TODO: we could decide to use cues for this, as we do for video.

+        //But we only use it for video because looking around for a keyframe

+        //can get expensive.  Audio doesn't require anything special so a

+        //straight cluster search is good enough (we assume).

+

+        Cluster** lo = i;

+        Cluster** hi = j;

+

+        while (lo < hi)

+        {

+            //INVARIANT:

+            //[i, lo) <= time_ns

+            //[lo, hi) ?

+            //[hi, j)  > time_ns

+

+            Cluster** const mid = lo + (hi - lo) / 2;

+            assert(mid < hi);

+

+            Cluster* const pCluster = *mid;

+            assert(pCluster);

+            assert(pCluster->m_index == long(mid - m_clusters));

+            assert(pCluster->m_pSegment == this);

+

+            const long long t = pCluster->GetTime();

+

+            if (t <= time_ns)

+                lo = mid + 1;

+            else

+                hi = mid;

+

+            assert(lo <= hi);

+        }

+

+        assert(lo == hi);

+        assert(lo > i);

+        assert(lo <= j);

+

+        Cluster* const pCluster = *--lo;

+        assert(pCluster);

+        assert(pCluster->GetTime() <= time_ns);

+

+        return pCluster->GetEntry(pTrack);

+    }

+

+    assert(pTrack->GetType() == 1);  //video

+

+    Cluster** lo = i;

+    Cluster** hi = j;

+

+    while (lo < hi)

+    {

+        //INVARIANT:

+        //[i, lo) <= time_ns

+        //[lo, hi) ?

+        //[hi, j)  > time_ns

+

+        Cluster** const mid = lo + (hi - lo) / 2;

+        assert(mid < hi);

+

+        Cluster* const pCluster = *mid;

+        assert(pCluster);

+

+        const long long t = pCluster->GetTime();

+

+        if (t <= time_ns)

+            lo = mid + 1;

+        else

+            hi = mid;

+

+        assert(lo <= hi);

+    }

+

+    assert(lo == hi);

+    assert(lo > i);

+    assert(lo <= j);

+

+    Cluster* pCluster = *--lo;

+    assert(pCluster);

+    assert(pCluster->GetTime() <= time_ns);

+

+    {

+        const BlockEntry* const pBlockEntry = pCluster->GetEntry(pTrack);

+        assert(pBlockEntry);

+

+        if (!pBlockEntry->EOS())  //found a keyframe

+        {

+            const Block* const pBlock = pBlockEntry->GetBlock();

+            assert(pBlock);

+

+            //TODO: this isn't necessarily the keyframe we want,

+            //since there might another keyframe on this same

+            //cluster with a greater timecode that but that is

+            //still less than the requested time.  For now we

+            //simply return the first keyframe we find.

+

+            if (pBlock->GetTime(pCluster) <= time_ns)

+                return pBlockEntry;

+        }

+    }

+

+    const VideoTrack* const pVideo = static_cast<const VideoTrack*>(pTrack);

+

+    while (lo != i)

+    {

+        pCluster = *--lo;

+        assert(pCluster);

+        assert(pCluster->GetTime() <= time_ns);

+

+        const BlockEntry* const pBlockEntry = pCluster->GetMaxKey(pVideo);

+        assert(pBlockEntry);

+

+        if (!pBlockEntry->EOS())

+            return pBlockEntry;

+    }

+

+    //weird: we're on the first cluster, but no keyframe found

+    //should never happen but we must return something anyway

+

+    return pTrack->GetEOS();

+}

+

+

+#if 0

+bool Segment::SearchCues(

+    long long time_ns,

+    Track* pTrack,

+    Cluster*& pCluster,

+    const BlockEntry*& pBlockEntry,

+    const CuePoint*& pCP,

+    const CuePoint::TrackPosition*& pTP)

+{

+    if (pTrack->GetType() != 1)  //not video

+        return false;  //TODO: for now, just handle video stream

+

+    if (m_pCues == NULL)

+        return false;

+

+    if (!m_pCues->Find(time_ns, pTrack, pCP, pTP))

+        return false;  //weird

+

+    assert(pCP);

+    assert(pTP);

+    assert(pTP->m_track == pTrack->GetNumber());

+

+    //We have the cue point and track position we want,

+    //so we now need to search for the cluster having

+    //the indicated position.

+

+    return GetCluster(pCP, pTP, pCluster, pBlockEntry);

+}

+#endif

+

+

+Tracks* Segment::GetTracks() const

+{

+    return m_pTracks;

+}

+

+

+const SegmentInfo* Segment::GetInfo() const

+{

+    return m_pInfo;

+}

+

+

+const Cues* Segment::GetCues() const

+{

+    return m_pCues;

+}

+

+

+long long Segment::GetDuration() const

+{

+    assert(m_pInfo);

+    return m_pInfo->GetDuration();

+}

+

+

+SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_) :

+    m_pSegment(pSegment),

+    m_start(start),

+    m_size(size_),

+    m_pMuxingAppAsUTF8(NULL),

+    m_pWritingAppAsUTF8(NULL),

+    m_pTitleAsUTF8(NULL)

+{

+    IMkvReader* const pReader = m_pSegment->m_pReader;

+

+    long long pos = start;

+    const long long stop = start + size_;

+

+    m_timecodeScale = 1000000;

+    m_duration = -1;

+

+    while (pos < stop)

+    {

+        if (Match(pReader, pos, 0x0AD7B1, m_timecodeScale))

+            assert(m_timecodeScale > 0);

+

+        else if (Match(pReader, pos, 0x0489, m_duration))

+            assert(m_duration >= 0);

+

+        else if (Match(pReader, pos, 0x0D80, m_pMuxingAppAsUTF8))   //[4D][80]

+            assert(m_pMuxingAppAsUTF8);

+

+        else if (Match(pReader, pos, 0x1741, m_pWritingAppAsUTF8))  //[57][41]

+            assert(m_pWritingAppAsUTF8);

+

+        else if (Match(pReader, pos, 0x3BA9, m_pTitleAsUTF8))       //[7B][A9]

+            assert(m_pTitleAsUTF8);

+

+        else

+        {

+            long len;

+

+            const long long id = ReadUInt(pReader, pos, len);

+            //id;

+            assert(id >= 0);

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume id

+            assert((stop - pos) > 0);

+

+            const long long size = ReadUInt(pReader, pos, len);

+            assert(size >= 0);

+            assert((pos + len) <= stop);

+

+            pos += len + size;  //consume size and payload

+            assert(pos <= stop);

+        }

+    }

+

+    assert(pos == stop);

+}

+

+SegmentInfo::~SegmentInfo()

+{

+    if (m_pMuxingAppAsUTF8)

+    {

+        delete[] m_pMuxingAppAsUTF8;

+        m_pMuxingAppAsUTF8 = NULL;

+    }

+

+    if (m_pWritingAppAsUTF8)

+    {

+        delete[] m_pWritingAppAsUTF8;

+        m_pWritingAppAsUTF8 = NULL;

+    }

+

+    if (m_pTitleAsUTF8)

+    {

+        delete[] m_pTitleAsUTF8;

+        m_pTitleAsUTF8 = NULL;

+    }

+}

+

+long long SegmentInfo::GetTimeCodeScale() const

+{

+    return m_timecodeScale;

+}

+

+

+long long SegmentInfo::GetDuration() const

+{

+    if (m_duration < 0)

+        return -1;

+

+    assert(m_timecodeScale >= 1);

+

+    const double dd = double(m_duration) * double(m_timecodeScale);

+    const long long d = static_cast<long long>(dd);

+

+    return d;

+}

+

+const char* SegmentInfo::GetMuxingAppAsUTF8() const

+{

+    return m_pMuxingAppAsUTF8;

+}

+

+

+const char* SegmentInfo::GetWritingAppAsUTF8() const

+{

+    return m_pWritingAppAsUTF8;

+}

+

+const char* SegmentInfo::GetTitleAsUTF8() const

+{

+    return m_pTitleAsUTF8;

+}

+

+Track::Track(Segment* pSegment, const Info& i) :

+    m_pSegment(pSegment),

+    m_info(i)

+{

+}

+

+Track::~Track()

+{

+    Info& info = const_cast<Info&>(m_info);

+    info.Clear();

+}

+

+Track::Info::Info():

+    type(-1),

+    number(-1),

+    uid(-1),

+    nameAsUTF8(NULL),

+    codecId(NULL),

+    codecPrivate(NULL),

+    codecPrivateSize(0),

+    codecNameAsUTF8(NULL)

+{

+}

+

+

+void Track::Info::Clear()

+{

+    delete[] nameAsUTF8;

+    nameAsUTF8 = NULL;

+

+    delete[] codecId;

+    codecId = NULL;

+

+    delete[] codecPrivate;

+    codecPrivate = NULL;

+

+    codecPrivateSize = 0;

+

+    delete[] codecNameAsUTF8;

+    codecNameAsUTF8 = NULL;

+}

+

+const BlockEntry* Track::GetEOS() const

+{

+    return &m_eos;

+}

+

+long long Track::GetType() const

+{

+    return m_info.type;

+}

+

+long long Track::GetNumber() const

+{

+    return m_info.number;

+}

+

+const char* Track::GetNameAsUTF8() const

+{

+    return m_info.nameAsUTF8;

+}

+

+const char* Track::GetCodecNameAsUTF8() const

+{

+    return m_info.codecNameAsUTF8;

+}

+

+

+const char* Track::GetCodecId() const

+{

+    return m_info.codecId;

+}

+

+const unsigned char* Track::GetCodecPrivate(size_t& size) const

+{

+    size = m_info.codecPrivateSize;

+    return m_info.codecPrivate;

+}

+

+

+long Track::GetFirst(const BlockEntry*& pBlockEntry) const

+{

+    Cluster* pCluster = m_pSegment->GetFirst();

+

+    //If Segment::GetFirst returns NULL, then this must be a network

+    //download, and we haven't loaded any clusters yet.  In this case,

+    //returning NULL from Track::GetFirst means the same thing.

+

+    for (int i = 0; i < 100; ++i)  //arbitrary upper bound

+    {

+        if (pCluster == NULL)

+        {

+            pBlockEntry = GetEOS();

+            return 1;

+        }

+

+        if (pCluster->EOS())

+        {

+            if (m_pSegment->Unparsed() <= 0)  //all clusters have been loaded

+            {

+                pBlockEntry = GetEOS();

+                return 1;

+            }

+

+            pBlockEntry = 0;

+            return E_BUFFER_NOT_FULL;

+        }

+

+        pBlockEntry = pCluster->GetFirst();

+

+        while (pBlockEntry)

+        {

+            const Block* const pBlock = pBlockEntry->GetBlock();

+            assert(pBlock);

+

+            if (pBlock->GetTrackNumber() == m_info.number)

+                return 0;

+

+            pBlockEntry = pCluster->GetNext(pBlockEntry);

+        }

+

+        pCluster = m_pSegment->GetNext(pCluster);

+    }

+

+    //NOTE: if we get here, it means that we didn't find a block with

+    //a matching track number.  We interpret that as an error (which

+    //might be too conservative).

+

+    pBlockEntry = GetEOS();  //so we can return a non-NULL value

+    return 1;

+}

+

+

+long Track::GetNext(

+    const BlockEntry* pCurrEntry,

+    const BlockEntry*& pNextEntry) const

+{

+    assert(pCurrEntry);

+    assert(!pCurrEntry->EOS());  //?

+

+    const Block* const pCurrBlock = pCurrEntry->GetBlock();

+    assert(pCurrBlock->GetTrackNumber() == m_info.number);

+

+    Cluster* pCluster = pCurrEntry->GetCluster();

+    assert(pCluster);

+    assert(!pCluster->EOS());

+

+    pNextEntry = pCluster->GetNext(pCurrEntry);

+

+    for (int i = 0; i < 100; ++i)  //arbitrary upper bound to search

+    {

+        while (pNextEntry)

+        {

+            const Block* const pNextBlock = pNextEntry->GetBlock();

+            assert(pNextBlock);

+

+            if (pNextBlock->GetTrackNumber() == m_info.number)

+                return 0;

+

+            pNextEntry = pCluster->GetNext(pNextEntry);

+        }

+

+        pCluster = m_pSegment->GetNext(pCluster);

+

+        if (pCluster == NULL)

+        {

+            pNextEntry = GetEOS();

+            return 1;

+        }

+

+        if (pCluster->EOS())

+        {

+            if (m_pSegment->Unparsed() <= 0)   //all clusters have been loaded

+            {

+                pNextEntry = GetEOS();

+                return 1;

+            }

+

+            //TODO: there is a potential O(n^2) problem here: we tell the

+            //caller to (pre)load another cluster, which he does, but then he

+            //calls GetNext again, which repeats the same search.  This is

+            //a pathological case, since the only way it can happen is if

+            //there exists a long sequence of clusters none of which contain a

+            // block from this track.  One way around this problem is for the

+            //caller to be smarter when he loads another cluster: don't call

+            //us back until you have a cluster that contains a block from this

+            //track. (Of course, that's not cheap either, since our caller

+            //would have to scan the each cluster as it's loaded, so that

+            //would just push back the problem.)

+

+            pNextEntry = NULL;

+            return E_BUFFER_NOT_FULL;

+        }

+

+        pNextEntry = pCluster->GetFirst();

+    }

+

+    //NOTE: if we get here, it means that we didn't find a block with

+    //a matching track number after lots of searching, so we give

+    //up trying.

+

+    pNextEntry = GetEOS();  //so we can return a non-NULL value

+    return 1;

+}

+

+

+Track::EOSBlock::EOSBlock()

+{

+}

+

+

+bool Track::EOSBlock::EOS() const

+{

+    return true;

+}

+

+

+Cluster* Track::EOSBlock::GetCluster() const

+{

+    return NULL;

+}

+

+

+size_t Track::EOSBlock::GetIndex() const

+{

+    return 0;

+}

+

+

+const Block* Track::EOSBlock::GetBlock() const

+{

+    return NULL;

+}

+

+

+bool Track::EOSBlock::IsBFrame() const

+{

+    return false;

+}

+

+

+VideoTrack::VideoTrack(Segment* pSegment, const Info& i) :

+    Track(pSegment, i),

+    m_width(-1),

+    m_height(-1),

+    m_rate(-1)

+{

+    assert(i.type == 1);

+    assert(i.number > 0);

+

+    IMkvReader* const pReader = pSegment->m_pReader;

+

+    const Settings& s = i.settings;

+    assert(s.start >= 0);

+    assert(s.size >= 0);

+

+    long long pos = s.start;

+    assert(pos >= 0);

+

+    const long long stop = pos + s.size;

+

+    while (pos < stop)

+    {

+#ifdef _DEBUG

+        long len;

+        const long long id = ReadUInt(pReader, pos, len);

+        assert(id >= 0);  //TODO: handle error case

+        assert((pos + len) <= stop);

+#endif

+        if (Match(pReader, pos, 0x30, m_width))

+            ;

+        else if (Match(pReader, pos, 0x3A, m_height))

+            ;

+        else if (Match(pReader, pos, 0x0383E3, m_rate))

+            ;

+        else

+        {

+            long len;

+            const long long id = ReadUInt(pReader, pos, len);

+            assert(id >= 0);  //TODO: handle error case

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume id

+

+            const long long size = ReadUInt(pReader, pos, len);

+            assert(size >= 0);  //TODO: handle error case

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume length of size

+            assert((pos + size) <= stop);

+

+            //pos now designates start of payload

+

+            pos += size;  //consume payload

+            assert(pos <= stop);

+        }

+    }

+

+    return;

+}

+

+

+bool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const

+{

+    assert(pBlockEntry);

+

+    const Block* const pBlock = pBlockEntry->GetBlock();

+    assert(pBlock);

+    assert(pBlock->GetTrackNumber() == m_info.number);

+

+    return pBlock->IsKey();

+}

+

+

+long long VideoTrack::GetWidth() const

+{

+    return m_width;

+}

+

+

+long long VideoTrack::GetHeight() const

+{

+    return m_height;

+}

+

+

+double VideoTrack::GetFrameRate() const

+{

+    return m_rate;

+}

+

+

+AudioTrack::AudioTrack(Segment* pSegment, const Info& i) :

+    Track(pSegment, i),

+    m_rate(0.0),

+    m_channels(0),

+    m_bitDepth(-1)

+{

+    assert(i.type == 2);

+    assert(i.number > 0);

+

+    IMkvReader* const pReader = pSegment->m_pReader;

+

+    const Settings& s = i.settings;

+    assert(s.start >= 0);

+    assert(s.size >= 0);

+

+    long long pos = s.start;

+    assert(pos >= 0);

+

+    const long long stop = pos + s.size;

+

+    while (pos < stop)

+    {

+#ifdef _DEBUG

+        long len;

+        const long long id = ReadUInt(pReader, pos, len);

+        assert(id >= 0);  //TODO: handle error case

+        assert((pos + len) <= stop);

+#endif

+        if (Match(pReader, pos, 0x35, m_rate))

+            ;

+        else if (Match(pReader, pos, 0x1F, m_channels))

+            ;

+        else if (Match(pReader, pos, 0x2264, m_bitDepth))

+            ;

+        else

+        {

+            long len;

+            const long long id = ReadUInt(pReader, pos, len);

+            assert(id >= 0);  //TODO: handle error case

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume id

+

+            const long long size = ReadUInt(pReader, pos, len);

+            assert(size >= 0);  //TODO: handle error case

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume length of size

+            assert((pos + size) <= stop);

+

+            //pos now designates start of payload

+

+            pos += size;  //consume payload

+            assert(pos <= stop);

+        }

+    }

+

+    return;

+}

+

+

+bool AudioTrack::VetEntry(const BlockEntry* pBlockEntry) const

+{

+    assert(pBlockEntry);

+

+    const Block* const pBlock = pBlockEntry->GetBlock();

+    assert(pBlock);

+    assert(pBlock->GetTrackNumber() == m_info.number);

+

+    return true;

+}

+

+

+double AudioTrack::GetSamplingRate() const

+{

+    return m_rate;

+}

+

+

+long long AudioTrack::GetChannels() const

+{

+    return m_channels;

+}

+

+long long AudioTrack::GetBitDepth() const

+{

+    return m_bitDepth;

+}

+

+Tracks::Tracks(Segment* pSegment, long long start, long long size_) :

+    m_pSegment(pSegment),

+    m_start(start),

+    m_size(size_),

+    m_trackEntries(NULL),

+    m_trackEntriesEnd(NULL)

+{

+    long long stop = m_start + m_size;

+    IMkvReader* const pReader = m_pSegment->m_pReader;

+

+    long long pos1 = m_start;

+    int count = 0;

+

+    while (pos1 < stop)

+    {

+        long len;

+        const long long id = ReadUInt(pReader, pos1, len);

+        assert(id >= 0);

+        assert((pos1 + len) <= stop);

+

+        pos1 += len;  //consume id

+

+        const long long size = ReadUInt(pReader, pos1, len);

+        assert(size >= 0);

+        assert((pos1 + len) <= stop);

+

+        pos1 += len;  //consume length of size

+

+        //pos now desinates start of element

+        if (id == 0x2E)  //TrackEntry ID

+            ++count;

+

+        pos1 += size;  //consume payload

+        assert(pos1 <= stop);

+    }

+

+    if (count <= 0)

+        return;

+

+    m_trackEntries = new Track*[count];

+    m_trackEntriesEnd = m_trackEntries;

+

+    long long pos = m_start;

+

+    while (pos < stop)

+    {

+        long len;

+        const long long id = ReadUInt(pReader, pos, len);

+        assert(id >= 0);

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume id

+

+        const long long size1 = ReadUInt(pReader, pos, len);

+        assert(size1 >= 0);

+        assert((pos + len) <= stop);

+

+        pos += len;  //consume length of size

+

+        //pos now desinates start of element

+

+        if (id == 0x2E)  //TrackEntry ID

+            ParseTrackEntry(pos, size1, *m_trackEntriesEnd++);

+

+        pos += size1;  //consume payload

+        assert(pos <= stop);

+    }

+}

+

+

+unsigned long Tracks::GetTracksCount() const

+{

+    const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries;

+    assert(result >= 0);

+

+    return static_cast<unsigned long>(result);

+}

+

+

+void Tracks::ParseTrackEntry(

+    long long start,

+    long long size,

+    Track*& pTrack)

+{

+    IMkvReader* const pReader = m_pSegment->m_pReader;

+

+    long long pos = start;

+    const long long stop = start + size;

+

+    Track::Info i;

+

+    Track::Settings videoSettings;

+    videoSettings.start = -1;

+

+    Track::Settings audioSettings;

+    audioSettings.start = -1;

+

+    while (pos < stop)

+    {

+#ifdef _DEBUG

+        long len;

+        const long long id = ReadUInt(pReader, pos, len);

+        len;

+        id;

+#endif

+        if (Match(pReader, pos, 0x57, i.number))

+            assert(i.number > 0);

+        else if (Match(pReader, pos, 0x33C5, i.uid))

+            ;

+        else if (Match(pReader, pos, 0x03, i.type))

+            ;

+        else if (Match(pReader, pos, 0x136E, i.nameAsUTF8))

+            assert(i.nameAsUTF8);

+        else if (Match(pReader, pos, 0x06, i.codecId))

+            ;

+        else if (Match(pReader,

+                       pos,

+                       0x23A2,

+                       i.codecPrivate,

+                       i.codecPrivateSize))

+            ;

+        else if (Match(pReader, pos, 0x058688, i.codecNameAsUTF8))

+            assert(i.codecNameAsUTF8);

+        else

+        {

+            long len;

+

+            const long long id = ReadUInt(pReader, pos, len);

+            assert(id >= 0);  //TODO: handle error case

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume id

+

+            const long long size = ReadUInt(pReader, pos, len);

+            assert(size >= 0);  //TODO: handle error case

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume length of size

+            const long long start = pos;

+

+            pos += size;  //consume payload

+            assert(pos <= stop);

+

+            if (id == 0x60)

+            {

+                videoSettings.start = start;

+                videoSettings.size = size;

+            }

+            else if (id == 0x61)

+            {

+                audioSettings.start = start;

+                audioSettings.size = size;

+            }

+        }

+    }

+

+    assert(pos == stop);

+    //TODO: propertly vet info.number, to ensure both its existence,

+    //and that it is unique among all tracks.

+    assert(i.number > 0);

+

+    //TODO: vet settings, to ensure that video settings (0x60)

+    //were specified when type = 1, and that audio settings (0x61)

+    //were specified when type = 2.

+    if (i.type == 1)  //video

+    {

+        assert(audioSettings.start < 0);

+        assert(videoSettings.start >= 0);

+

+        i.settings = videoSettings;

+

+        VideoTrack* const t = new VideoTrack(m_pSegment, i);

+        assert(t);  //TODO

+        pTrack = t;

+    }

+    else if (i.type == 2)  //audio

+    {

+        assert(videoSettings.start < 0);

+        assert(audioSettings.start >= 0);

+

+        i.settings = audioSettings;

+

+        AudioTrack* const t = new  AudioTrack(m_pSegment, i);

+        assert(t);  //TODO

+        pTrack = t;

+    }

+    else

+    {

+        // for now we do not support other track types yet.

+        // TODO: support other track types

+        i.Clear();

+

+        pTrack = NULL;

+    }

+

+    return;

+}

+

+

+Tracks::~Tracks()

+{

+    Track** i = m_trackEntries;

+    Track** const j = m_trackEntriesEnd;

+

+    while (i != j)

+    {

+        Track* const pTrack = *i++;

+        delete pTrack;

+    }

+

+    delete[] m_trackEntries;

+}

+

+

+Track* Tracks::GetTrackByNumber(unsigned long tn_) const

+{

+    const long long tn = tn_;

+

+    Track** i = m_trackEntries;

+    Track** const j = m_trackEntriesEnd;

+

+    while (i != j)

+    {

+        Track* const pTrack = *i++;

+

+        if (pTrack == NULL)

+            continue;

+

+        if (tn == pTrack->GetNumber())

+            return pTrack;

+    }

+

+    return NULL;  //not found

+}

+

+

+Track* Tracks::GetTrackByIndex(unsigned long idx) const

+{

+    const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries;

+

+    if (idx >= static_cast<unsigned long>(count))

+         return NULL;

+

+    return m_trackEntries[idx];

+}

+

+

+void Cluster::Load()

+{

+    assert(m_pSegment);

+    assert(m_pos);

+    assert(m_size);

+

+    if (m_pos > 0)  //loaded

+    {

+        assert(m_size > 0);

+        assert(m_timecode >= 0);

+        return;

+    }

+

+    assert(m_pos < 0);  //not loaded yet

+    assert(m_size < 0);

+    assert(m_timecode < 0);

+

+    IMkvReader* const pReader = m_pSegment->m_pReader;

+

+    m_pos *= -1;                                  //relative to segment

+    long long pos = m_pSegment->m_start + m_pos;  //absolute

+

+    long len;

+

+    const long long id_ = ReadUInt(pReader, pos, len);

+    assert(id_ >= 0);

+    assert(id_ == 0x0F43B675);  //Cluster ID

+

+    pos += len;  //consume id

+

+    const long long size_ = ReadUInt(pReader, pos, len);

+    assert(size_ >= 0);

+

+    pos += len;  //consume size

+

+    m_size = size_;

+    const long long stop = pos + size_;

+

+    long long timecode = -1;

+

+    while (pos < stop)

+    {

+        if (Match(pReader, pos, 0x67, timecode))

+            break;

+        else

+        {

+            const long long id = ReadUInt(pReader, pos, len);

+            assert(id >= 0);  //TODO

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume id

+

+            const long long size = ReadUInt(pReader, pos, len);

+            assert(size >= 0);  //TODO

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume size

+

+            if (id == 0x20)  //BlockGroup ID

+                break;

+

+            if (id == 0x23)  //SimpleBlock ID

+                break;

+

+            pos += size;  //consume payload

+            assert(pos <= stop);

+        }

+    }

+

+    assert(pos <= stop);

+    assert(timecode >= 0);

+

+    m_timecode = timecode;

+}

+

+

+Cluster* Cluster::Parse(

+    Segment* pSegment,

+    long idx,

+    long long off)

+{

+    assert(pSegment);

+    assert(off >= 0);

+    assert(off < pSegment->m_size);

+

+    Cluster* const pCluster = new Cluster(pSegment, idx, -off);

+    assert(pCluster);

+

+    return pCluster;

+}

+

+

+Cluster::Cluster() :

+    m_pSegment(NULL),

+    m_index(0),

+    m_pos(0),

+    m_size(0),

+    m_timecode(0),

+    m_entries(NULL),

+    m_entriesCount(0)

+{

+}

+

+

+Cluster::Cluster(

+    Segment* pSegment,

+    long idx,

+    long long off) :

+    m_pSegment(pSegment),

+    m_index(idx),

+    m_pos(off),

+    m_size(-1),

+    m_timecode(-1),

+    m_entries(NULL),

+    m_entriesCount(0)

+{

+}

+

+

+Cluster::~Cluster()

+{

+    BlockEntry** i = m_entries;

+    BlockEntry** const j = m_entries + m_entriesCount;

+

+    while (i != j)

+    {

+         BlockEntry* p = *i++;

+         assert(p);

+

+         delete p;

+    }

+

+    delete[] m_entries;

+}

+

+

+bool Cluster::EOS() const

+{

+    return (m_pSegment == NULL);

+}

+

+

+void Cluster::LoadBlockEntries()

+{

+    if (m_entries)

+        return;

+

+    assert(m_pSegment);

+    assert(m_pos);

+    assert(m_size);

+    assert(m_entriesCount == 0);

+

+    IMkvReader* const pReader = m_pSegment->m_pReader;

+

+    if (m_pos < 0)

+        m_pos *= -1;  //relative to segment

+

+    long long pos = m_pSegment->m_start + m_pos;  //absolute

+

+    {

+        long len;

+

+        const long long id = ReadUInt(pReader, pos, len);

+        id;

+        assert(id >= 0);

+        assert(id == 0x0F43B675);  //Cluster ID

+

+        pos += len;  //consume id

+

+        const long long size = ReadUInt(pReader, pos, len);

+        assert(size > 0);

+

+        pos += len;  //consume size

+

+        //pos now points to start of payload

+

+        if (m_size >= 0)

+            assert(size == m_size);

+        else

+            m_size = size;

+    }

+

+    const long long stop = pos + m_size;

+    long long timecode = -1;  //of cluster itself

+

+    //First count the number of entries

+

+    long long idx = pos;  //points to start of payload

+    m_entriesCount = 0;

+

+    while (idx < stop)

+    {

+        if (Match(pReader, idx, 0x67, timecode))

+        {

+            if (m_timecode >= 0)

+                assert(timecode == m_timecode);

+            else

+                m_timecode = timecode;

+        }

+        else

+        {

+            long len;

+

+            const long long id = ReadUInt(pReader, idx, len);

+            assert(id >= 0);  //TODO

+            assert((idx + len) <= stop);

+

+            idx += len;  //consume id

+

+            const long long size = ReadUInt(pReader, idx, len);

+            assert(size >= 0);  //TODO

+            assert((idx + len) <= stop);

+

+            idx += len;  //consume size

+

+            if (id == 0x20)  //BlockGroup ID

+                ++m_entriesCount;

+            else if (id == 0x23)  //SimpleBlock ID

+                ++m_entriesCount;

+

+            idx += size;  //consume payload

+            assert(idx <= stop);

+        }

+    }

+

+    assert(idx == stop);

+    assert(m_timecode >= 0);

+

+    if (m_entriesCount == 0)  //TODO: handle empty clusters

+        return;

+

+    m_entries = new BlockEntry*[m_entriesCount];

+    size_t index = 0;

+

+    while (pos < stop)

+    {

+        if (Match(pReader, pos, 0x67, timecode))

+            assert(timecode == m_timecode);

+        else

+        {

+            long len;

+            const long long id = ReadUInt(pReader, pos, len);

+            assert(id >= 0);  //TODO

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume id

+

+            const long long size = ReadUInt(pReader, pos, len);

+            assert(size >= 0);  //TODO

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume size

+

+            if (id == 0x20)  //BlockGroup ID

+                ParseBlockGroup(pos, size, index++);

+            else if (id == 0x23)  //SimpleBlock ID

+                ParseSimpleBlock(pos, size, index++);

+

+            pos += size;  //consume payload

+            assert(pos <= stop);

+        }

+    }

+

+    assert(pos == stop);

+    assert(timecode >= 0);

+    assert(index == m_entriesCount);

+}

+

+

+

+long long Cluster::GetTimeCode()

+{

+    Load();

+    return m_timecode;

+}

+

+

+long long Cluster::GetTime()

+{

+    const long long tc = GetTimeCode();

+    assert(tc >= 0);

+

+    const SegmentInfo* const pInfo = m_pSegment->GetInfo();

+    assert(pInfo);

+

+    const long long scale = pInfo->GetTimeCodeScale();

+    assert(scale >= 1);

+

+    const long long t = m_timecode * scale;

+

+    return t;

+}

+

+

+long long Cluster::GetFirstTime()

+{

+    const BlockEntry* const pEntry = GetFirst();

+

+    if (pEntry == NULL)  //empty cluster

+        return GetTime();

+

+    const Block* const pBlock = pEntry->GetBlock();

+    assert(pBlock);

+

+    return pBlock->GetTime(this);

+}

+

+

+long long Cluster::GetLastTime()

+{

+    const BlockEntry* const pEntry = GetLast();

+

+    if (pEntry == NULL)  //empty cluster

+        return GetTime();

+

+    const Block* const pBlock = pEntry->GetBlock();

+    assert(pBlock);

+

+    return pBlock->GetTime(this);

+}

+

+

+void Cluster::ParseBlockGroup(long long start, long long size, size_t index)

+{

+    assert(m_entries);

+    assert(m_entriesCount);

+    assert(index < m_entriesCount);

+

+    BlockGroup* const pGroup =

+        new (std::nothrow) BlockGroup(this, index, start, size);

+    assert(pGroup);  //TODO

+

+    m_entries[index] = pGroup;

+}

+

+

+

+void Cluster::ParseSimpleBlock(long long start, long long size, size_t index)

+{

+    assert(m_entries);

+    assert(m_entriesCount);

+    assert(index < m_entriesCount);

+

+    SimpleBlock* const pSimpleBlock =

+        new (std::nothrow) SimpleBlock(this, index, start, size);

+    assert(pSimpleBlock);  //TODO

+

+    m_entries[index] = pSimpleBlock;

+}

+

+

+const BlockEntry* Cluster::GetFirst()

+{

+    LoadBlockEntries();

+    //assert(m_entries);

+    //assert(m_entriesCount >= 1);

+

+    if ((m_entries == NULL) || (m_entriesCount == 0))

+        return NULL;

+

+    const BlockEntry* const pFirst = m_entries[0];

+    assert(pFirst);

+

+    return pFirst;

+}

+

+

+const BlockEntry* Cluster::GetLast()

+{

+    LoadBlockEntries();

+    //assert(m_entries);

+    //assert(m_entriesCount >= 1);

+

+    if ((m_entries == NULL) || (m_entriesCount == 0))

+        return NULL;

+

+    const size_t idx = m_entriesCount - 1;

+

+    const BlockEntry* const pLast = m_entries[idx];

+    assert(pLast);

+

+    return pLast;

+}

+

+

+const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const

+{

+    assert(pEntry);

+    assert(m_entries);

+    assert(m_entriesCount);

+

+    size_t idx = pEntry->GetIndex();

+    assert(idx < m_entriesCount);

+    assert(m_entries[idx] == pEntry);

+

+    ++idx;

+

+    if (idx >= m_entriesCount)

+      return NULL;

+

+    return m_entries[idx];

+}

+

+

+const BlockEntry* Cluster::GetEntry(const Track* pTrack)

+{

+    assert(pTrack);

+

+    if (m_pSegment == NULL)  //EOS

+        return pTrack->GetEOS();

+

+    LoadBlockEntries();

+

+    if ((m_entries == NULL) || (m_entriesCount == 0))

+        return NULL;

+

+    BlockEntry** i = m_entries;

+    assert(i);

+

+    BlockEntry** const j = i + m_entriesCount;

+

+    while (i != j)

+    {

+        const BlockEntry* const pEntry = *i++;

+        assert(pEntry);

+        assert(!pEntry->EOS());

+

+        const Block* const pBlock = pEntry->GetBlock();

+        assert(pBlock);

+

+        if (pBlock->GetTrackNumber() != pTrack->GetNumber())

+            continue;

+

+        if (pTrack->VetEntry(pEntry))

+            return pEntry;

+    }

+

+    return pTrack->GetEOS();  //no satisfactory block found

+}

+

+

+const BlockEntry*

+Cluster::GetEntry(

+    const CuePoint& cp,

+    const CuePoint::TrackPosition& tp)

+{

+    assert(m_pSegment);

+

+    LoadBlockEntries();

+

+    if (m_entries == NULL)

+        return NULL;

+

+    const long long count = m_entriesCount;

+

+    if (count <= 0)

+        return NULL;

+

+    const long long tc = cp.GetTimeCode();

+

+    if ((tp.m_block > 0) && (tp.m_block <= count))

+    {

+        const size_t block = static_cast<size_t>(tp.m_block);

+        const size_t index = block - 1;

+

+        const BlockEntry* const pEntry = m_entries[index];

+        assert(pEntry);

+        assert(!pEntry->EOS());

+

+        const Block* const pBlock = pEntry->GetBlock();

+        assert(pBlock);

+

+        if ((pBlock->GetTrackNumber() == tp.m_track) &&

+            (pBlock->GetTimeCode(this) == tc))

+        {

+            return pEntry;

+        }

+    }

+

+    const BlockEntry* const* i = m_entries;

+    const BlockEntry* const* const j = i + count;

+

+    while (i != j)

+    {

+        const BlockEntry* const pEntry = *i++;

+        assert(pEntry);

+        assert(!pEntry->EOS());

+

+        const Block* const pBlock = pEntry->GetBlock();

+        assert(pBlock);

+

+        if (pBlock->GetTrackNumber() != tp.m_track)

+            continue;

+

+        const long long tc_ = pBlock->GetTimeCode(this);

+

+        if (tc_ < tc)

+            continue;

+

+        if (tc_ > tc)

+            return NULL;

+

+        const Tracks* const pTracks = m_pSegment->GetTracks();

+        assert(pTracks);

+

+        const long tn = static_cast<long>(tp.m_track);

+        const Track* const pTrack = pTracks->GetTrackByNumber(tn);

+

+        if (pTrack == NULL)

+            return NULL;

+

+        const long long type = pTrack->GetType();

+

+        if (type == 2)  //audio

+            return pEntry;

+

+        if (type != 1)  //not video

+            return NULL;

+

+        if (!pBlock->IsKey())

+            return NULL;

+

+        return pEntry;

+    }

+

+    return NULL;

+}

+

+

+const BlockEntry* Cluster::GetMaxKey(const VideoTrack* pTrack)

+{

+    assert(pTrack);

+

+    if (m_pSegment == NULL)  //EOS

+        return pTrack->GetEOS();

+

+    LoadBlockEntries();

+    //assert(m_entries);

+

+    BlockEntry** i = m_entries + m_entriesCount;

+    BlockEntry** const j = m_entries;

+

+    while (i != j)

+    {

+        const BlockEntry* const pEntry = *--i;

+        assert(pEntry);

+        assert(!pEntry->EOS());

+

+        const Block* const pBlock = pEntry->GetBlock();

+        assert(pBlock);

+

+        if (pBlock->GetTrackNumber() != pTrack->GetNumber())

+            continue;

+

+        if (pBlock->IsKey())

+            return pEntry;

+    }

+

+    return pTrack->GetEOS();  //no satisfactory block found

+}

+

+

+

+BlockEntry::BlockEntry()

+{

+}

+

+

+BlockEntry::~BlockEntry()

+{

+}

+

+

+SimpleBlock::SimpleBlock(

+    Cluster* pCluster,

+    size_t idx,

+    long long start,

+    long long size) :

+    m_pCluster(pCluster),

+    m_index(idx),

+    m_block(start, size, pCluster->m_pSegment->m_pReader)

+{

+}

+

+

+bool SimpleBlock::EOS() const

+{

+    return false;

+}

+

+

+Cluster* SimpleBlock::GetCluster() const

+{

+    return m_pCluster;

+}

+

+

+size_t SimpleBlock::GetIndex() const

+{

+    return m_index;

+}

+

+

+const Block* SimpleBlock::GetBlock() const

+{

+    return &m_block;

+}

+

+

+bool SimpleBlock::IsBFrame() const

+{

+    return false;

+}

+

+

+BlockGroup::BlockGroup(

+    Cluster* pCluster,

+    size_t idx,

+    long long start,

+    long long size_) :

+    m_pCluster(pCluster),

+    m_index(idx),

+    m_prevTimeCode(0),

+    m_nextTimeCode(0),

+    m_pBlock(NULL)  //TODO: accept multiple blocks within a block group

+{

+    IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;

+

+    long long pos = start;

+    const long long stop = start + size_;

+

+    bool bSimpleBlock = false;

+    bool bReferenceBlock = false;

+

+    while (pos < stop)

+    {

+        short t;

+

+        if (Match(pReader, pos, 0x7B, t))

+        {

+            if (t < 0)

+                m_prevTimeCode = t;

+            else if (t > 0)

+                m_nextTimeCode = t;

+            else

+                assert(false);

+

+            bReferenceBlock = true;

+        }

+        else

+        {

+            long len;

+            const long long id = ReadUInt(pReader, pos, len);

+            assert(id >= 0);  //TODO

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume ID

+

+            const long long size = ReadUInt(pReader, pos, len);

+            assert(size >= 0);  //TODO

+            assert((pos + len) <= stop);

+

+            pos += len;  //consume size

+

+            switch (id)

+            {

+                case 0x23:  //SimpleBlock ID

+                    bSimpleBlock = true;

+                    //YES, FALL THROUGH TO NEXT CASE

+

+                case 0x21:  //Block ID

+                    ParseBlock(pos, size);

+                    break;

+

+                default:

+                    break;

+            }

+

+            pos += size;  //consume payload

+            assert(pos <= stop);

+        }

+    }

+

+    assert(pos == stop);

+    assert(m_pBlock);

+

+    if (!bSimpleBlock)

+        m_pBlock->SetKey(!bReferenceBlock);

+}

+

+

+BlockGroup::~BlockGroup()

+{

+    delete m_pBlock;

+}

+

+

+void BlockGroup::ParseBlock(long long start, long long size)

+{

+    IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;

+

+    Block* const pBlock = new Block(start, size, pReader);

+    assert(pBlock);  //TODO

+

+    //TODO: the Matroska spec says you have multiple blocks within the

+    //same block group, with blocks ranked by priority (the flag bits).

+

+    assert(m_pBlock == NULL);

+    m_pBlock = pBlock;

+}

+

+

+bool BlockGroup::EOS() const

+{

+    return false;

+}

+

+

+Cluster* BlockGroup::GetCluster() const

+{

+    return m_pCluster;

+}

+

+

+size_t BlockGroup::GetIndex() const

+{

+    return m_index;

+}

+

+

+const Block* BlockGroup::GetBlock() const

+{

+    return m_pBlock;

+}

+

+

+short BlockGroup::GetPrevTimeCode() const

+{

+    return m_prevTimeCode;

+}

+

+

+short BlockGroup::GetNextTimeCode() const

+{

+    return m_nextTimeCode;

+}

+

+

+bool BlockGroup::IsBFrame() const

+{

+    return (m_nextTimeCode > 0);

+}

+

+

+

+Block::Block(long long start, long long size_, IMkvReader* pReader) :

+    m_start(start),

+    m_size(size_)

+{

+    long long pos = start;

+    const long long stop = start + size_;

+

+    long len;

+

+    m_track = ReadUInt(pReader, pos, len);

+    assert(m_track > 0);

+    assert((pos + len) <= stop);

+

+    pos += len;  //consume track number

+    assert((stop - pos) >= 2);

+

+    m_timecode = Unserialize2SInt(pReader, pos);

+

+    pos += 2;

+    assert((stop - pos) >= 1);

+

+    const long hr = pReader->Read(pos, 1, &m_flags);

+    assert(hr == 0L);

+

+    ++pos;

+    assert(pos <= stop);

+

+    m_frameOff = pos;

+

+    const long long frame_size = stop - pos;

+

+    assert(frame_size <= 2147483647L);

+

+    m_frameSize = static_cast<long>(frame_size);

+}

+

+

+long long Block::GetTimeCode(Cluster* pCluster) const

+{

+    assert(pCluster);

+

+    const long long tc0 = pCluster->GetTimeCode();

+    assert(tc0 >= 0);

+

+    const long long tc = tc0 + static_cast<long long>(m_timecode);

+    assert(tc >= 0);

+

+    return tc;  //unscaled timecode units

+}

+

+

+long long Block::GetTime(Cluster* pCluster) const

+{

+    assert(pCluster);

+

+    const long long tc = GetTimeCode(pCluster);

+

+    const Segment* const pSegment = pCluster->m_pSegment;

+    const SegmentInfo* const pInfo = pSegment->GetInfo();

+    assert(pInfo);

+

+    const long long scale = pInfo->GetTimeCodeScale();

+    assert(scale >= 1);

+

+    const long long ns = tc * scale;

+

+    return ns;

+}

+

+

+long long Block::GetTrackNumber() const

+{

+    return m_track;

+}

+

+

+bool Block::IsKey() const

+{

+    return ((m_flags & static_cast<unsigned char>(1 << 7)) != 0);

+}

+

+

+void Block::SetKey(bool bKey)

+{

+    if (bKey)

+        m_flags |= static_cast<unsigned char>(1 << 7);

+    else

+        m_flags &= 0x7F;

+}

+

+

+long long Block::GetOffset() const

+{

+  return m_frameOff;

+}

+

+

+long Block::GetSize() const

+{

+    return m_frameSize;

+}

+

+

+long Block::Read(IMkvReader* pReader, unsigned char* buf) const

+{

+

+    assert(pReader);

+    assert(buf);

+

+    const long hr = pReader->Read(m_frameOff, m_frameSize, buf);

+

+    return hr;

+}

+

+

+}  //end namespace mkvparser

diff --git a/media/libstagefright/matroska/mkvparser.hpp b/media/libstagefright/matroska/mkvparser.hpp
index 4d311b4..c46d349 100644
--- a/media/libstagefright/matroska/mkvparser.hpp
+++ b/media/libstagefright/matroska/mkvparser.hpp
@@ -1,428 +1,554 @@
-#ifndef MKVPARSER_HPP
-#define MKVPARSER_HPP
-
-#include <cstdlib>
-#include <cstdio>
-
-namespace mkvparser
-{
-
-const int E_FILE_FORMAT_INVALID = -2;
-const int E_BUFFER_NOT_FULL = -3;
-
-class IMkvReader
-{
-public:
-    virtual int Read(long long position, long length, unsigned char* buffer) = 0;
-    virtual int Length(long long* total, long long* available) = 0; 	
-protected:
-    virtual ~IMkvReader();
-};
-
-long long GetUIntLength(IMkvReader*, long long, long&);
-long long ReadUInt(IMkvReader*, long long, long&);
-long long SyncReadUInt(IMkvReader*, long long pos, long long stop, long&);
-long long UnserializeUInt(IMkvReader*, long long pos, long long size);
-float Unserialize4Float(IMkvReader*, long long);
-double Unserialize8Double(IMkvReader*, long long);
-short Unserialize2SInt(IMkvReader*, long long);
-signed char Unserialize1SInt(IMkvReader*, long long);
-bool Match(IMkvReader*, long long&, unsigned long, long long&);
-bool Match(IMkvReader*, long long&, unsigned long, char*&);
-bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&,
-           size_t *optionalSize = NULL);
-bool Match(IMkvReader*, long long&, unsigned long, double&);
-bool Match(IMkvReader*, long long&, unsigned long, short&);
-
-
-struct EBMLHeader
-{
-    EBMLHeader();
-    ~EBMLHeader();  
-    long long m_version;
-    long long m_readVersion;
-    long long m_maxIdLength;
-    long long m_maxSizeLength;
-    char* m_docType;
-    long long m_docTypeVersion;
-    long long m_docTypeReadVersion;
-    
-    long long Parse(IMkvReader*, long long&);
-};
-
-
-class Segment;
-class Track;
-class Cluster;
-
-class Block
-{
-    Block(const Block&);
-    Block& operator=(const Block&);
-
-public:
-    const long long m_start;
-    const long long m_size;
-    
-    Block(long long start, long long size, IMkvReader*);
-    
-    unsigned long GetTrackNumber() const;
-    
-    long long GetTimeCode(Cluster*) const;  //absolute, but not scaled
-    long long GetTime(Cluster*) const;      //absolute, and scaled (nanosecond units)
-    bool IsKey() const;
-    void SetKey(bool);
-
-    long GetSize() const;
-    long Read(IMkvReader*, unsigned char*) const;
-    
-private:
-    long long m_track;   //Track::Number()
-    short m_timecode;  //relative to cluster
-    unsigned char m_flags;
-    long long m_frameOff;
-    long m_frameSize;    
-
-};
-
-
-class BlockEntry
-{
-    BlockEntry(const BlockEntry&);
-    BlockEntry& operator=(const BlockEntry&);
-    
-public:
-    virtual ~BlockEntry();
-    virtual bool EOS() const = 0;
-    virtual Cluster* GetCluster() const = 0;
-    virtual size_t GetIndex() const = 0;
-    virtual const Block* GetBlock() const = 0;
-    virtual bool IsBFrame() const = 0;
-    
-protected:
-    BlockEntry();
-
-};
-
-
-class SimpleBlock : public BlockEntry
-{
-    SimpleBlock(const SimpleBlock&);
-    SimpleBlock& operator=(const SimpleBlock&);
-
-public:
-    SimpleBlock(Cluster*, size_t, long long start, long long size);
-
-    bool EOS() const;
-    Cluster* GetCluster() const; 
-    size_t GetIndex() const;
-    const Block* GetBlock() const;
-    bool IsBFrame() const;
-
-protected:
-    Cluster* const m_pCluster;
-    const size_t m_index;
-    Block m_block;
-    
-};
-
-
-class BlockGroup : public BlockEntry
-{
-    BlockGroup(const BlockGroup&);
-    BlockGroup& operator=(const BlockGroup&);
-
-public:
-    BlockGroup(Cluster*, size_t, long long, long long);
-    ~BlockGroup();
-    
-    bool EOS() const;
-    Cluster* GetCluster() const; 
-    size_t GetIndex() const;
-    const Block* GetBlock() const;
-    bool IsBFrame() const;
-    
-    short GetPrevTimeCode() const;  //relative to block's time
-    short GetNextTimeCode() const;  //as above
-    
-protected:
-    Cluster* const m_pCluster;
-    const size_t m_index;
-    
-private:
-    BlockGroup(Cluster*, size_t, unsigned long);
-    void ParseBlock(long long start, long long size);
-
-    short m_prevTimeCode;
-    short m_nextTimeCode;
-    
-    //TODO: the Matroska spec says you can have multiple blocks within the 
-    //same block group, with blocks ranked by priority (the flag bits).
-    //For now we just cache a single block.
-#if 0
-    typedef std::deque<Block*> blocks_t;
-    blocks_t m_blocks;  //In practice should contain only a single element.
-#else
-    Block* m_pBlock;
-#endif
-    
-};
-
-
-class Track
-{
-    Track(const Track&);
-    Track& operator=(const Track&);
-
-public:    
-    Segment* const m_pSegment;
-    virtual ~Track();
-    
-    long long GetType() const; 
-    unsigned long GetNumber() const;
-    const char* GetNameAsUTF8() const;
-    const char* GetCodecNameAsUTF8() const;
-    const char* GetCodecId() const;
-    const unsigned char* GetCodecPrivate(
-            size_t *optionalSize = NULL) const;
-    
-    const BlockEntry* GetEOS() const;
-    
-    struct Settings 
-    {
-        long long start;
-        long long size;
-    };
-    
-    struct Info
-    {
-        long long type;
-        long long number;
-        long long uid;
-        char* nameAsUTF8;
-        char* codecId;
-        unsigned char* codecPrivate;
-        size_t codecPrivateSize;
-        char* codecNameAsUTF8;
-        Settings settings;
-        Info();
-        void Clear();
-    };
-    
-    long GetFirst(const BlockEntry*&) const;
-    long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;
-    virtual bool VetEntry(const BlockEntry*) const = 0;
-        
-protected:
-    Track(Segment*, const Info&);        
-    const Info m_info;
-
-    class EOSBlock : public BlockEntry
-    {
-    public:
-        EOSBlock();
-
-        bool EOS() const;    
-        Cluster* GetCluster() const;
-        size_t GetIndex() const;
-        const Block* GetBlock() const;
-        bool IsBFrame() const;
-    };
-    
-    EOSBlock m_eos;
-    
-};
-
-
-class VideoTrack : public Track
-{
-    VideoTrack(const VideoTrack&);
-    VideoTrack& operator=(const VideoTrack&);
-    
-public:
-    VideoTrack(Segment*, const Info&);    
-    long long GetWidth() const;
-    long long GetHeight() const;
-    double GetFrameRate() const;
-    
-    bool VetEntry(const BlockEntry*) const;
-
-private:
-    long long m_width;
-    long long m_height;
-    double m_rate;
-    
-};
-
-
-class AudioTrack : public Track
-{
-    AudioTrack(const AudioTrack&);
-    AudioTrack& operator=(const AudioTrack&);
-
-public:
-    AudioTrack(Segment*, const Info&);    
-    double GetSamplingRate() const;
-    long long GetChannels() const;
-    long long GetBitDepth() const;    
-    bool VetEntry(const BlockEntry*) const;
-
-private:
-    double m_rate;
-    long long m_channels;
-    long long m_bitDepth;
-};
-
-
-class Tracks
-{
-    Tracks(const Tracks&);
-    Tracks& operator=(const Tracks&);
-
-public:
-    Segment* const m_pSegment;
-    const long long m_start;
-    const long long m_size;
-    
-    Tracks(Segment*, long long start, long long size);
-    virtual ~Tracks();
-
-    Track* GetTrackByNumber(unsigned long tn) const;
-    Track* GetTrackByIndex(unsigned long idx) const;
-    
-private:
-    Track** m_trackEntries; 
-    Track** m_trackEntriesEnd;
-
-    void ParseTrackEntry(long long, long long, Track*&);
-    
-public:
-    unsigned long GetTracksCount() const;
-};
-
-
-class SegmentInfo
-{
-    SegmentInfo(const SegmentInfo&);
-    SegmentInfo& operator=(const SegmentInfo&);
-    
-public:
-    Segment* const m_pSegment;
-    const long long m_start;
-    const long long m_size;
-    
-    SegmentInfo(Segment*, long long start, long long size);
-    ~SegmentInfo();
-    long long GetTimeCodeScale() const;
-    long long GetDuration() const;  //scaled
-    const char* GetMuxingAppAsUTF8() const;
-    const char* GetWritingAppAsUTF8() const;
-    const char* GetTitleAsUTF8() const;
-    
-private:
-    long long m_timecodeScale;
-    double m_duration;
-    char* m_pMuxingAppAsUTF8;
-    char* m_pWritingAppAsUTF8;
-    char* m_pTitleAsUTF8;
-};
-
-
-class Cluster
-{
-    Cluster(const Cluster&);
-    Cluster& operator=(const Cluster&);
-
-public:
-    Segment* const m_pSegment;
-    const size_t m_index;
-    
-public:    
-    static Cluster* Parse(Segment*, size_t, long long off);
-
-    Cluster();  //EndOfStream
-    ~Cluster();
-    
-    bool EOS() const;
-    
-    long long GetTimeCode();  //absolute, but not scaled
-    long long GetTime();      //absolute, and scaled (nanosecond units)
-
-    const BlockEntry* GetFirst();
-    const BlockEntry* GetLast();
-    const BlockEntry* GetNext(const BlockEntry*) const;    
-    const BlockEntry* GetEntry(const Track*);
-protected:    
-    Cluster(Segment*, size_t, long long off);
-    
-private:
-    long long m_start;
-    long long m_size;    
-    long long m_timecode;
-    BlockEntry** m_pEntries;
-    size_t m_entriesCount;
-   
-    void Load();
-    void LoadBlockEntries();
-    void ParseBlockGroup(long long, long long, size_t);
-    void ParseSimpleBlock(long long, long long, size_t);
-    
-};
-
-
-class Segment
-{
-    Segment(const Segment&);
-    Segment& operator=(const Segment&);
-
-private:
-    Segment(IMkvReader*, long long pos, long long size);
-
-public:
-    IMkvReader* const m_pReader;
-    const long long m_start;  //posn of segment payload
-    const long long m_size;   //size of segment payload
-    Cluster m_eos;  //TODO: make private?
-    
-    static long long CreateInstance(IMkvReader*, long long, Segment*&);
-    ~Segment();
-
-    //for big-bang loading (source filter)
-    long Load();
-
-    //for incremental loading (splitter)    
-    long long Unparsed() const;
-    long long ParseHeaders();
-    long ParseCluster(Cluster*&, long long& newpos) const;
-    bool AddCluster(Cluster*, long long);
-
-    Tracks* GetTracks() const;    
-    const SegmentInfo* const GetInfo() const;
-    long long GetDuration() const;
-    
-    //NOTE: this turned out to be too inefficient.
-    //long long Load(long long time_nanoseconds);
-
-    Cluster* GetFirst();
-    Cluster* GetLast();
-    unsigned long GetCount() const;
-    
-    Cluster* GetNext(const Cluster*);
-    Cluster* GetCluster(long long time_nanoseconds);
-    
-private:
-    long long m_pos;  //absolute file posn; what has been consumed so far    
-    SegmentInfo* m_pInfo;
-    Tracks* m_pTracks;    
-    Cluster** m_clusters;
-    size_t m_clusterCount;
-
-    void ParseSeekHead(long long pos, long long size, size_t*);
-    void ParseSeekEntry(long long pos, long long size, size_t*);
-    void ParseSecondarySeekHead(long long off, size_t*);
-};
-
-
-}  //end namespace mkvparser
-
-#endif  //MKVPARSER_HPP
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.

+//

+// Use of this source code is governed by a BSD-style license

+// that can be found in the LICENSE file in the root of the source

+// tree. An additional intellectual property rights grant can be found

+// in the file PATENTS.  All contributing project authors may

+// be found in the AUTHORS file in the root of the source tree.

+

+#ifndef MKVPARSER_HPP

+#define MKVPARSER_HPP

+

+#include <cstdlib>

+#include <cstdio>

+

+namespace mkvparser

+{

+

+const int E_FILE_FORMAT_INVALID = -2;

+const int E_BUFFER_NOT_FULL = -3;

+

+class IMkvReader

+{

+public:

+    virtual int Read(long long pos, long len, unsigned char* buf) = 0;

+    virtual int Length(long long* total, long long* available) = 0;

+protected:

+    virtual ~IMkvReader();

+};

+

+long long GetUIntLength(IMkvReader*, long long, long&);

+long long ReadUInt(IMkvReader*, long long, long&);

+long long SyncReadUInt(IMkvReader*, long long pos, long long stop, long&);

+long long UnserializeUInt(IMkvReader*, long long pos, long long size);

+float Unserialize4Float(IMkvReader*, long long);

+double Unserialize8Double(IMkvReader*, long long);

+short Unserialize2SInt(IMkvReader*, long long);

+signed char Unserialize1SInt(IMkvReader*, long long);

+bool Match(IMkvReader*, long long&, unsigned long, long long&);

+bool Match(IMkvReader*, long long&, unsigned long, char*&);

+bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&, size_t&);

+bool Match(IMkvReader*, long long&, unsigned long, double&);

+bool Match(IMkvReader*, long long&, unsigned long, short&);

+

+void GetVersion(int& major, int& minor, int& build, int& revision);

+

+struct EBMLHeader

+{

+    EBMLHeader();

+    ~EBMLHeader();

+    long long m_version;

+    long long m_readVersion;

+    long long m_maxIdLength;

+    long long m_maxSizeLength;

+    char* m_docType;

+    long long m_docTypeVersion;

+    long long m_docTypeReadVersion;

+

+    long long Parse(IMkvReader*, long long&);

+};

+

+

+class Segment;

+class Track;

+class Cluster;

+

+class Block

+{

+    Block(const Block&);

+    Block& operator=(const Block&);

+

+public:

+    const long long m_start;

+    const long long m_size;

+

+    Block(long long start, long long size, IMkvReader*);

+

+    long long GetTrackNumber() const;

+    long long GetTimeCode(Cluster*) const;  //absolute, but not scaled

+    long long GetTime(Cluster*) const;      //absolute, and scaled (ns units)

+    bool IsKey() const;

+    void SetKey(bool);

+

+    long long GetOffset() const;

+    long GetSize() const;

+    long Read(IMkvReader*, unsigned char*) const;

+

+private:

+    long long m_track;   //Track::Number()

+    short m_timecode;  //relative to cluster

+    unsigned char m_flags;

+    long long m_frameOff;

+    long m_frameSize;

+

+};

+

+

+class BlockEntry

+{

+    BlockEntry(const BlockEntry&);

+    BlockEntry& operator=(const BlockEntry&);

+

+public:

+    virtual ~BlockEntry();

+    virtual bool EOS() const = 0;

+    virtual Cluster* GetCluster() const = 0;

+    virtual size_t GetIndex() const = 0;

+    virtual const Block* GetBlock() const = 0;

+    virtual bool IsBFrame() const = 0;

+

+protected:

+    BlockEntry();

+

+};

+

+

+class SimpleBlock : public BlockEntry

+{

+    SimpleBlock(const SimpleBlock&);

+    SimpleBlock& operator=(const SimpleBlock&);

+

+public:

+    SimpleBlock(Cluster*, size_t, long long start, long long size);

+

+    bool EOS() const;

+    Cluster* GetCluster() const;

+    size_t GetIndex() const;

+    const Block* GetBlock() const;

+    bool IsBFrame() const;

+

+protected:

+    Cluster* const m_pCluster;

+    const size_t m_index;

+    Block m_block;

+

+};

+

+

+class BlockGroup : public BlockEntry

+{

+    BlockGroup(const BlockGroup&);

+    BlockGroup& operator=(const BlockGroup&);

+

+public:

+    BlockGroup(Cluster*, size_t, long long, long long);

+    ~BlockGroup();

+

+    bool EOS() const;

+    Cluster* GetCluster() const;

+    size_t GetIndex() const;

+    const Block* GetBlock() const;

+    bool IsBFrame() const;

+

+    short GetPrevTimeCode() const;  //relative to block's time

+    short GetNextTimeCode() const;  //as above

+

+protected:

+    Cluster* const m_pCluster;

+    const size_t m_index;

+

+private:

+    BlockGroup(Cluster*, size_t, unsigned long);

+    void ParseBlock(long long start, long long size);

+

+    short m_prevTimeCode;

+    short m_nextTimeCode;

+

+    //TODO: the Matroska spec says you can have multiple blocks within the

+    //same block group, with blocks ranked by priority (the flag bits).

+    //For now we just cache a single block.

+#if 0

+    typedef std::deque<Block*> blocks_t;

+    blocks_t m_blocks;  //In practice should contain only a single element.

+#else

+    Block* m_pBlock;

+#endif

+

+};

+

+

+class Track

+{

+    Track(const Track&);

+    Track& operator=(const Track&);

+

+public:

+    Segment* const m_pSegment;

+    virtual ~Track();

+

+    long long GetType() const;

+    long long GetNumber() const;

+    const char* GetNameAsUTF8() const;

+    const char* GetCodecNameAsUTF8() const;

+    const char* GetCodecId() const;

+    const unsigned char* GetCodecPrivate(size_t&) const;

+

+    const BlockEntry* GetEOS() const;

+

+    struct Settings

+    {

+        long long start;

+        long long size;

+    };

+

+    struct Info

+    {

+        long long type;

+        long long number;

+        long long uid;

+        char* nameAsUTF8;

+        char* codecId;

+        unsigned char* codecPrivate;

+        size_t codecPrivateSize;

+        char* codecNameAsUTF8;

+        Settings settings;

+        Info();

+        void Clear();

+    };

+

+    long GetFirst(const BlockEntry*&) const;

+    long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;

+    virtual bool VetEntry(const BlockEntry*) const = 0;

+

+protected:

+    Track(Segment*, const Info&);

+    const Info m_info;

+

+    class EOSBlock : public BlockEntry

+    {

+    public:

+        EOSBlock();

+

+        bool EOS() const;

+        Cluster* GetCluster() const;

+        size_t GetIndex() const;

+        const Block* GetBlock() const;

+        bool IsBFrame() const;

+    };

+

+    EOSBlock m_eos;

+

+};

+

+

+class VideoTrack : public Track

+{

+    VideoTrack(const VideoTrack&);

+    VideoTrack& operator=(const VideoTrack&);

+

+public:

+    VideoTrack(Segment*, const Info&);

+    long long GetWidth() const;

+    long long GetHeight() const;

+    double GetFrameRate() const;

+

+    bool VetEntry(const BlockEntry*) const;

+

+private:

+    long long m_width;

+    long long m_height;

+    double m_rate;

+

+};

+

+

+class AudioTrack : public Track

+{

+    AudioTrack(const AudioTrack&);

+    AudioTrack& operator=(const AudioTrack&);

+

+public:

+    AudioTrack(Segment*, const Info&);

+    double GetSamplingRate() const;

+    long long GetChannels() const;

+    long long GetBitDepth() const;

+    bool VetEntry(const BlockEntry*) const;

+

+private:

+    double m_rate;

+    long long m_channels;

+    long long m_bitDepth;

+};

+

+

+class Tracks

+{

+    Tracks(const Tracks&);

+    Tracks& operator=(const Tracks&);

+

+public:

+    Segment* const m_pSegment;

+    const long long m_start;

+    const long long m_size;

+

+    Tracks(Segment*, long long start, long long size);

+    virtual ~Tracks();

+

+    Track* GetTrackByNumber(unsigned long tn) const;

+    Track* GetTrackByIndex(unsigned long idx) const;

+

+private:

+    Track** m_trackEntries;

+    Track** m_trackEntriesEnd;

+

+    void ParseTrackEntry(long long, long long, Track*&);

+

+public:

+    unsigned long GetTracksCount() const;

+};

+

+

+class SegmentInfo

+{

+    SegmentInfo(const SegmentInfo&);

+    SegmentInfo& operator=(const SegmentInfo&);

+

+public:

+    Segment* const m_pSegment;

+    const long long m_start;

+    const long long m_size;

+

+    SegmentInfo(Segment*, long long start, long long size);

+    ~SegmentInfo();

+    long long GetTimeCodeScale() const;

+    long long GetDuration() const;  //scaled

+    const char* GetMuxingAppAsUTF8() const;

+    const char* GetWritingAppAsUTF8() const;

+    const char* GetTitleAsUTF8() const;

+

+private:

+    long long m_timecodeScale;

+    double m_duration;

+    char* m_pMuxingAppAsUTF8;

+    char* m_pWritingAppAsUTF8;

+    char* m_pTitleAsUTF8;

+};

+

+class Cues;

+class CuePoint

+{

+    friend class Cues;

+

+    CuePoint(size_t, long long);

+    ~CuePoint();

+

+    CuePoint(const CuePoint&);

+    CuePoint& operator=(const CuePoint&);

+

+public:

+    void Load(IMkvReader*);

+

+    long long GetTimeCode() const;      //absolute but unscaled

+    long long GetTime(Segment*) const;  //absolute and scaled (ns units)

+

+    struct TrackPosition

+    {

+        long long m_track;

+        long long m_pos;  //of cluster

+        long long m_block;

+        //codec_state  //defaults to 0

+        //reference = clusters containing req'd referenced blocks

+        //  reftime = timecode of the referenced block

+

+        void Parse(IMkvReader*, long long, long long);

+    };

+

+    const TrackPosition* Find(const Track*) const;

+

+private:

+    const size_t m_index;

+    long long m_timecode;

+    TrackPosition* m_track_positions;

+    size_t m_track_positions_count;

+

+};

+

+

+class Cues

+{

+    friend class Segment;

+

+    Cues(Segment*, long long start, long long size);

+    ~Cues();

+

+    Cues(const Cues&);

+    Cues& operator=(const Cues&);

+

+public:

+    Segment* const m_pSegment;

+    const long long m_start;

+    const long long m_size;

+

+    bool Find(  //lower bound of time_ns

+        long long time_ns,

+        const Track*,

+        const CuePoint*&,

+        const CuePoint::TrackPosition*&) const;

+

+#if 0

+    bool FindNext(  //upper_bound of time_ns

+        long long time_ns,

+        const Track*,

+        const CuePoint*&,

+        const CuePoint::TrackPosition*&) const;

+#endif

+

+    const CuePoint* GetFirst() const;

+    const CuePoint* GetLast() const;

+

+    const CuePoint* GetNext(const CuePoint*) const;

+

+    const BlockEntry* GetBlock(

+                        const CuePoint*,

+                        const CuePoint::TrackPosition*) const;

+

+private:

+    void Init() const;

+    bool LoadCuePoint() const;

+    void PreloadCuePoint(size_t&, long long) const;

+

+    mutable CuePoint** m_cue_points;

+    mutable size_t m_count;

+    mutable size_t m_preload_count;

+    mutable long long m_pos;

+

+};

+

+

+class Cluster

+{

+    Cluster(const Cluster&);

+    Cluster& operator=(const Cluster&);

+

+public:

+    Segment* const m_pSegment;

+

+public:

+    static Cluster* Parse(Segment*, long, long long off);

+

+    Cluster();  //EndOfStream

+    ~Cluster();

+

+    bool EOS() const;

+

+    long long GetTimeCode();   //absolute, but not scaled

+    long long GetTime();       //absolute, and scaled (nanosecond units)

+    long long GetFirstTime();  //time (ns) of first (earliest) block

+    long long GetLastTime();   //time (ns) of last (latest) block

+

+    const BlockEntry* GetFirst();

+    const BlockEntry* GetLast();

+    const BlockEntry* GetNext(const BlockEntry*) const;

+    const BlockEntry* GetEntry(const Track*);

+    const BlockEntry* GetEntry(

+        const CuePoint&,

+        const CuePoint::TrackPosition&);

+    const BlockEntry* GetMaxKey(const VideoTrack*);

+

+protected:

+    Cluster(Segment*, long, long long off);

+

+public:

+    //TODO: these should all be private, with public selector functions

+    long m_index;

+    long long m_pos;

+    long long m_size;

+

+private:

+    long long m_timecode;

+    BlockEntry** m_entries;

+    size_t m_entriesCount;

+

+    void Load();

+    void LoadBlockEntries();

+    void ParseBlockGroup(long long, long long, size_t);

+    void ParseSimpleBlock(long long, long long, size_t);

+

+};

+

+

+class Segment

+{

+    friend class Cues;

+

+    Segment(const Segment&);

+    Segment& operator=(const Segment&);

+

+private:

+    Segment(IMkvReader*, long long pos, long long size);

+

+public:

+    IMkvReader* const m_pReader;

+    const long long m_start;  //posn of segment payload

+    const long long m_size;   //size of segment payload

+    Cluster m_eos;  //TODO: make private?

+

+    static long long CreateInstance(IMkvReader*, long long, Segment*&);

+    ~Segment();

+

+    long Load();  //loads headers and all clusters

+

+    //for incremental loading (splitter)

+    long long Unparsed() const;

+    long long ParseHeaders();  //stops when first cluster is found

+    long LoadCluster();        //loads one cluster

+

+#if 0

+    //This pair parses one cluster, but only changes the state of the

+    //segment object when the cluster is actually added to the index.

+    long ParseCluster(Cluster*&, long long& newpos) const;

+    bool AddCluster(Cluster*, long long);

+#endif

+

+    Tracks* GetTracks() const;

+    const SegmentInfo* GetInfo() const;

+    const Cues* GetCues() const;

+

+    long long GetDuration() const;

+

+    unsigned long GetCount() const;

+    Cluster* GetFirst();

+    Cluster* GetLast();

+    Cluster* GetNext(const Cluster*);

+

+    Cluster* FindCluster(long long time_nanoseconds);

+    const BlockEntry* Seek(long long time_nanoseconds, const Track*);

+

+private:

+

+    long long m_pos;  //absolute file posn; what has been consumed so far

+    SegmentInfo* m_pInfo;

+    Tracks* m_pTracks;

+    Cues* m_pCues;

+    Cluster** m_clusters;

+    long m_clusterCount;         //number of entries for which m_index >= 0

+    long m_clusterPreloadCount;  //number of entries for which m_index < 0

+    long m_clusterSize;          //array size

+

+    void AppendCluster(Cluster*);

+    void PreloadCluster(Cluster*, ptrdiff_t);

+

+    void ParseSeekHead(long long pos, long long size);

+    void ParseSeekEntry(long long pos, long long size);

+    void ParseCues(long long);

+

+    const BlockEntry* GetBlock(

+        const CuePoint&,

+        const CuePoint::TrackPosition&);

+

+};

+

+

+}  //end namespace mkvparser

+

+#endif  //MKVPARSER_HPP

diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
index b0d2c64..bbde516 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -18,18 +18,381 @@
 
 #include "ARTPSource.h"
 
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include <ctype.h>
 
 namespace android {
 
-AMPEG4AudioAssembler::AMPEG4AudioAssembler(const sp<AMessage> &notify)
+static bool GetAttribute(const char *s, const char *key, AString *value) {
+    value->clear();
+
+    size_t keyLen = strlen(key);
+
+    for (;;) {
+        while (isspace(*s)) {
+            ++s;
+        }
+
+        const char *colonPos = strchr(s, ';');
+
+        size_t len =
+            (colonPos == NULL) ? strlen(s) : colonPos - s;
+
+        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
+            value->setTo(&s[keyLen + 1], len - keyLen - 1);
+            return true;
+        }
+
+        if (colonPos == NULL) {
+            return false;
+        }
+
+        s = colonPos + 1;
+    }
+}
+
+static sp<ABuffer> decodeHex(const AString &s) {
+    if ((s.size() % 2) != 0) {
+        return NULL;
+    }
+
+    size_t outLen = s.size() / 2;
+    sp<ABuffer> buffer = new ABuffer(outLen);
+    uint8_t *out = buffer->data();
+
+    uint8_t accum = 0;
+    for (size_t i = 0; i < s.size(); ++i) {
+        char c = s.c_str()[i];
+        unsigned value;
+        if (c >= '0' && c <= '9') {
+            value = c - '0';
+        } else if (c >= 'a' && c <= 'f') {
+            value = c - 'a' + 10;
+        } else if (c >= 'A' && c <= 'F') {
+            value = c - 'A' + 10;
+        } else {
+            return NULL;
+        }
+
+        accum = (accum << 4) | value;
+
+        if (i & 1) {
+            *out++ = accum;
+
+            accum = 0;
+        }
+    }
+
+    return buffer;
+}
+
+static status_t parseAudioObjectType(
+        ABitReader *bits, unsigned *audioObjectType) {
+    *audioObjectType = bits->getBits(5);
+    if ((*audioObjectType) == 31) {
+        *audioObjectType = 32 + bits->getBits(6);
+    }
+
+    return OK;
+}
+
+static status_t parseGASpecificConfig(
+        ABitReader *bits,
+        unsigned audioObjectType, unsigned channelConfiguration) {
+    unsigned frameLengthFlag = bits->getBits(1);
+    unsigned dependsOnCoreCoder = bits->getBits(1);
+    if (dependsOnCoreCoder) {
+        /* unsigned coreCoderDelay = */bits->getBits(1);
+    }
+    unsigned extensionFlag = bits->getBits(1);
+
+    if (!channelConfiguration) {
+        // program_config_element
+        return ERROR_UNSUPPORTED;  // XXX to be implemented
+    }
+
+    if (audioObjectType == 6 || audioObjectType == 20) {
+        /* unsigned layerNr = */bits->getBits(3);
+    }
+
+    if (extensionFlag) {
+        if (audioObjectType == 22) {
+            /* unsigned numOfSubFrame = */bits->getBits(5);
+            /* unsigned layerLength = */bits->getBits(11);
+        } else if (audioObjectType == 17 || audioObjectType == 19
+                || audioObjectType == 20 || audioObjectType == 23) {
+            /* unsigned aacSectionDataResilienceFlag = */bits->getBits(1);
+            /* unsigned aacScalefactorDataResilienceFlag = */bits->getBits(1);
+            /* unsigned aacSpectralDataResilienceFlag = */bits->getBits(1);
+        }
+
+        unsigned extensionFlag3 = bits->getBits(1);
+        CHECK_EQ(extensionFlag3, 0u);  // TBD in version 3
+    }
+
+    return OK;
+}
+
+static status_t parseAudioSpecificConfig(ABitReader *bits) {
+    unsigned audioObjectType;
+    CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK);
+
+    unsigned samplingFreqIndex = bits->getBits(4);
+    if (samplingFreqIndex == 0x0f) {
+        /* unsigned samplingFrequency = */bits->getBits(24);
+    }
+
+    unsigned channelConfiguration = bits->getBits(4);
+
+    unsigned extensionAudioObjectType = 0;
+    unsigned sbrPresent = 0;
+
+    if (audioObjectType == 5) {
+        extensionAudioObjectType = audioObjectType;
+        sbrPresent = 1;
+        unsigned extensionSamplingFreqIndex = bits->getBits(4);
+        if (extensionSamplingFreqIndex == 0x0f) {
+            /* unsigned extensionSamplingFrequency = */bits->getBits(24);
+        }
+        CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK);
+    }
+
+    CHECK((audioObjectType >= 1 && audioObjectType <= 4)
+        || (audioObjectType >= 6 && audioObjectType <= 7)
+        || audioObjectType == 17
+        || (audioObjectType >= 19 && audioObjectType <= 23));
+
+    CHECK_EQ(parseGASpecificConfig(
+                bits, audioObjectType, channelConfiguration), (status_t)OK);
+
+    if (audioObjectType == 17
+            || (audioObjectType >= 19 && audioObjectType <= 27)) {
+        unsigned epConfig = bits->getBits(2);
+        if (epConfig == 2 || epConfig == 3) {
+            // ErrorProtectionSpecificConfig
+            return ERROR_UNSUPPORTED;  // XXX to be implemented
+
+            if (epConfig == 3) {
+                unsigned directMapping = bits->getBits(1);
+                CHECK_EQ(directMapping, 1u);
+            }
+        }
+    }
+
+#if 0
+    // This is not supported here as the upper layers did not explicitly
+    // signal the length of AudioSpecificConfig.
+
+    if (extensionAudioObjectType != 5 && bits->numBitsLeft() >= 16) {
+        unsigned syncExtensionType = bits->getBits(11);
+        if (syncExtensionType == 0x2b7) {
+            CHECK_EQ(parseAudioObjectType(bits, &extensionAudioObjectType),
+                     (status_t)OK);
+
+            sbrPresent = bits->getBits(1);
+
+            if (sbrPresent == 1) {
+                unsigned extensionSamplingFreqIndex = bits->getBits(4);
+                if (extensionSamplingFreqIndex == 0x0f) {
+                    /* unsigned extensionSamplingFrequency = */bits->getBits(24);
+                }
+            }
+        }
+    }
+#endif
+
+    return OK;
+}
+
+static status_t parseStreamMuxConfig(
+        ABitReader *bits,
+        unsigned *numSubFrames,
+        unsigned *frameLengthType,
+        bool *otherDataPresent,
+        unsigned *otherDataLenBits) {
+    unsigned audioMuxVersion = bits->getBits(1);
+
+    unsigned audioMuxVersionA = 0;
+    if (audioMuxVersion == 1) {
+        audioMuxVersionA = bits->getBits(1);
+    }
+
+    CHECK_EQ(audioMuxVersionA, 0u);  // otherwise future spec
+
+    if (audioMuxVersion != 0) {
+        return ERROR_UNSUPPORTED;  // XXX to be implemented;
+    }
+    CHECK_EQ(audioMuxVersion, 0u);  // XXX to be implemented
+
+    unsigned allStreamsSameTimeFraming = bits->getBits(1);
+    CHECK_EQ(allStreamsSameTimeFraming, 1u);  // There's only one stream.
+
+    *numSubFrames = bits->getBits(6);
+    unsigned numProgram = bits->getBits(4);
+    CHECK_EQ(numProgram, 0u);  // disabled in RTP LATM
+
+    unsigned numLayer = bits->getBits(3);
+    CHECK_EQ(numLayer, 0u);  // disabled in RTP LATM
+
+    if (audioMuxVersion == 0) {
+        // AudioSpecificConfig
+        CHECK_EQ(parseAudioSpecificConfig(bits), (status_t)OK);
+    } else {
+        TRESPASS();  // XXX to be implemented
+    }
+
+    *frameLengthType = bits->getBits(3);
+    switch (*frameLengthType) {
+        case 0:
+        {
+            /* unsigned bufferFullness = */bits->getBits(8);
+
+            // The "coreFrameOffset" does not apply since there's only
+            // a single layer.
+            break;
+        }
+
+        case 1:
+        {
+            /* unsigned frameLength = */bits->getBits(9);
+            break;
+        }
+
+        case 3:
+        case 4:
+        case 5:
+        {
+            /* unsigned CELPframeLengthTableIndex = */bits->getBits(6);
+            break;
+        }
+
+        case 6:
+        case 7:
+        {
+            /* unsigned HVXCframeLengthTableIndex = */bits->getBits(1);
+            break;
+        }
+
+        default:
+            break;
+    }
+
+    *otherDataPresent = bits->getBits(1);
+    *otherDataLenBits = 0;
+    if (*otherDataPresent) {
+        if (audioMuxVersion == 1) {
+            TRESPASS();  // XXX to be implemented
+        } else {
+            *otherDataLenBits = 0;
+
+            unsigned otherDataLenEsc;
+            do {
+                (*otherDataLenBits) <<= 8;
+                otherDataLenEsc = bits->getBits(1);
+                unsigned otherDataLenTmp = bits->getBits(8);
+                (*otherDataLenBits) += otherDataLenTmp;
+            } while (otherDataLenEsc);
+        }
+    }
+
+    unsigned crcCheckPresent = bits->getBits(1);
+    if (crcCheckPresent) {
+        /* unsigned crcCheckSum = */bits->getBits(8);
+    }
+
+    return OK;
+}
+
+sp<ABuffer> AMPEG4AudioAssembler::removeLATMFraming(const sp<ABuffer> &buffer) {
+    CHECK(!mMuxConfigPresent);  // XXX to be implemented
+
+    sp<ABuffer> out = new ABuffer(buffer->size());
+    out->setRange(0, 0);
+
+    size_t offset = 0;
+    uint8_t *ptr = buffer->data();
+
+    for (size_t i = 0; i <= mNumSubFrames; ++i) {
+        // parse PayloadLengthInfo
+
+        unsigned payloadLength = 0;
+
+        switch (mFrameLengthType) {
+            case 0:
+            {
+                unsigned muxSlotLengthBytes = 0;
+                unsigned tmp;
+                do {
+                    CHECK_LT(offset, buffer->size());
+                    tmp = ptr[offset++];
+                    muxSlotLengthBytes += tmp;
+                } while (tmp == 0xff);
+
+                payloadLength = muxSlotLengthBytes;
+                break;
+            }
+
+            default:
+                TRESPASS();  // XXX to be implemented
+                break;
+        }
+
+        CHECK_LE(offset + payloadLength, buffer->size());
+
+        memcpy(out->data() + out->size(), &ptr[offset], payloadLength);
+        out->setRange(0, out->size() + payloadLength);
+
+        offset += payloadLength;
+
+        if (mOtherDataPresent) {
+            // We want to stay byte-aligned.
+
+            CHECK((mOtherDataLenBits % 8) == 0);
+            CHECK_LE(offset + (mOtherDataLenBits / 8), buffer->size());
+            offset += mOtherDataLenBits / 8;
+        }
+    }
+
+    CHECK_EQ(offset, buffer->size());
+
+    return out;
+}
+
+AMPEG4AudioAssembler::AMPEG4AudioAssembler(
+        const sp<AMessage> &notify, const AString &params)
     : mNotifyMsg(notify),
+      mMuxConfigPresent(false),
       mAccessUnitRTPTime(0),
       mNextExpectedSeqNoValid(false),
       mNextExpectedSeqNo(0),
       mAccessUnitDamaged(false) {
+    AString val;
+    if (!GetAttribute(params.c_str(), "cpresent", &val)) {
+        mMuxConfigPresent = true;
+    } else if (val == "0") {
+        mMuxConfigPresent = false;
+    } else {
+        CHECK(val == "1");
+        mMuxConfigPresent = true;
+    }
+
+    CHECK(GetAttribute(params.c_str(), "config", &val));
+
+    sp<ABuffer> config = decodeHex(val);
+    CHECK(config != NULL);
+
+    ABitReader bits(config->data(), config->size());
+    status_t err = parseStreamMuxConfig(
+            &bits, &mNumSubFrames, &mFrameLengthType,
+            &mOtherDataPresent, &mOtherDataLenBits);
+
+    CHECK_EQ(err, (status_t)NO_ERROR);
 }
 
 AMPEG4AudioAssembler::~AMPEG4AudioAssembler() {
@@ -108,13 +471,7 @@
     while (it != mPackets.end()) {
         const sp<ABuffer> &unit = *it;
 
-        size_t n = 0;
-        while (unit->data()[n] == 0xff) {
-            ++n;
-        }
-        ++n;
-
-        totalSize += unit->size() - n;
+        totalSize += unit->size();
         ++it;
     }
 
@@ -124,20 +481,13 @@
     while (it != mPackets.end()) {
         const sp<ABuffer> &unit = *it;
 
-        size_t n = 0;
-        while (unit->data()[n] == 0xff) {
-            ++n;
-        }
-        ++n;
-
         memcpy((uint8_t *)accessUnit->data() + offset,
-               unit->data() + n, unit->size() - n);
-
-        offset += unit->size() - n;
+               unit->data(), unit->size());
 
         ++it;
     }
 
+    accessUnit = removeLATMFraming(accessUnit);
     CopyTimes(accessUnit, *mPackets.begin());
 
 #if 0
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.h b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h
index bf9f204..9cef94c 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.h
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h
@@ -27,9 +27,11 @@
 namespace android {
 
 struct AMessage;
+struct AString;
 
 struct AMPEG4AudioAssembler : public ARTPAssembler {
-    AMPEG4AudioAssembler(const sp<AMessage> &notify);
+    AMPEG4AudioAssembler(
+            const sp<AMessage> &notify, const AString &params);
 
 protected:
     virtual ~AMPEG4AudioAssembler();
@@ -40,6 +42,13 @@
 
 private:
     sp<AMessage> mNotifyMsg;
+
+    bool mMuxConfigPresent;
+    unsigned mNumSubFrames;
+    unsigned mFrameLengthType;
+    bool mOtherDataPresent;
+    unsigned mOtherDataLenBits;
+
     uint32_t mAccessUnitRTPTime;
     bool mNextExpectedSeqNoValid;
     uint32_t mNextExpectedSeqNo;
@@ -49,6 +58,8 @@
     AssemblyStatus addPacket(const sp<ARTPSource> &source);
     void submitAccessUnit();
 
+    sp<ABuffer> removeLATMFraming(const sp<ABuffer> &buffer);
+
     DISALLOW_EVIL_CONSTRUCTORS(AMPEG4AudioAssembler);
 };
 
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 2518264..5aae4e7 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -57,7 +57,7 @@
         mAssembler = new AAVCAssembler(notify);
         mIssueFIRRequests = true;
     } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
-        mAssembler = new AMPEG4AudioAssembler(notify);
+        mAssembler = new AMPEG4AudioAssembler(notify, params);
     } else if (!strncmp(desc.c_str(), "H263-1998/", 10)
             || !strncmp(desc.c_str(), "H263-2000/", 10)) {
         mAssembler = new AH263Assembler(notify);
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 880aa85..547fbab 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -53,7 +53,6 @@
     mFormats.push(AString("[root]"));
 
     AString desc((const char *)data, size);
-    LOGI("%s", desc.c_str());
 
     size_t i = 0;
     for (;;) {
@@ -76,6 +75,8 @@
             return false;
         }
 
+        LOGI("%s", line.c_str());
+
         switch (line.c_str()[0]) {
             case 'v':
             {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
index 3908d71..b4ae593 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
@@ -300,6 +300,7 @@
             if (duration <= 0){
                 assertTrue("stressRecordAndPlayback", false);
             }
+            mp.release();
         } catch (Exception e) {
             assertTrue("stressRecordAndPlayback", false);
         }
diff --git a/obex/javax/obex/ServerOperation.java b/obex/javax/obex/ServerOperation.java
index 07a3a53..d1476d2 100644
--- a/obex/javax/obex/ServerOperation.java
+++ b/obex/javax/obex/ServerOperation.java
@@ -397,11 +397,13 @@
                     && (headerID != ObexHelper.OBEX_OPCODE_GET_FINAL)) {
 
                 if (length > 3) {
-                    byte[] temp = new byte[length];
+                    byte[] temp = new byte[length - 3];
+                    // First three bytes already read, compensating for this
                     bytesReceived = mInput.read(temp);
 
-                    while (bytesReceived != length) {
-                        bytesReceived += mInput.read(temp, bytesReceived, length - bytesReceived);
+                    while (bytesReceived != temp.length) {
+                        bytesReceived += mInput.read(temp, bytesReceived,
+                                temp.length - bytesReceived);
                     }
                 }
 
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index c937b06..8f2f974 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -155,6 +155,8 @@
  *
  */
 public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
+    private final static String TAG = "GLSurfaceView";
+    private final static boolean LOG_ATTACH_DETACH = false;
     private final static boolean LOG_THREADS = false;
     private final static boolean LOG_PAUSE_RESUME = false;
     private final static boolean LOG_SURFACE = false;
@@ -306,6 +308,7 @@
         if (mEGLWindowSurfaceFactory == null) {
             mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
         }
+        mRenderer = renderer;
         mGLThread = new GLThread(renderer);
         mGLThread.start();
     }
@@ -525,10 +528,41 @@
     /**
      * This method is used as part of the View class and is not normally
      * called or subclassed by clients of GLSurfaceView.
+     */
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (LOG_ATTACH_DETACH) {
+            Log.d(TAG, "onAttachedToWindow reattach =" + mDetached);
+        }
+        if (mDetached && (mRenderer != null)) {
+            int renderMode = RENDERMODE_CONTINUOUSLY;
+            if (mGLThread != null) {
+                renderMode = mGLThread.getRenderMode();
+            }
+            mGLThread = new GLThread(mRenderer);
+            if (renderMode != RENDERMODE_CONTINUOUSLY) {
+                mGLThread.setRenderMode(renderMode);
+            }
+            mGLThread.start();
+        }
+        mDetached = false;
+    }
+
+    /**
+     * This method is used as part of the View class and is not normally
+     * called or subclassed by clients of GLSurfaceView.
      * Must not be called before a renderer has been set.
      */
     @Override
     protected void onDetachedFromWindow() {
+        if (LOG_ATTACH_DETACH) {
+            Log.d(TAG, "onDetachedFromWindow");
+        }
+        if (mGLThread != null) {
+            mGLThread.requestExitAndWait();
+        }
+        mDetached = true;
         super.onDetachedFromWindow();
     }
 
@@ -1726,6 +1760,8 @@
     private boolean mSizeChanged = true;
 
     private GLThread mGLThread;
+    private Renderer mRenderer;
+    private boolean mDetached;
     private EGLConfigChooser mEGLConfigChooser;
     private EGLContextFactory mEGLContextFactory;
     private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index e44c485..7c496e7 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -546,7 +546,9 @@
     if (!dirtyRegion.isEmpty()) {
         dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
         if (previousBuffer) {
-            const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
+            // This was const Region copyBack, but that causes an
+            // internal compile error on simulator builds
+            /*const*/ Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
             if (!copyBack.isEmpty()) {
                 void* prevBits;
                 if (lock(previousBuffer, 
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index ae924cd..c8041fc 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -8,6 +8,7 @@
 
 LOCAL_SRC_FILES:= 	       \
 	EGL/egl.cpp 	       \
+	EGL/trace.cpp              \
 	EGL/getProcAddress.cpp.arm \
 	EGL/hooks.cpp 	       \
 	EGL/Loader.cpp 	       \
@@ -33,6 +34,7 @@
 LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -DEGL_TRACE=1
 
 ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
 LOCAL_CFLAGS += -DADRENO130=1
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index bc944a0..f744b72 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -285,6 +285,58 @@
 EGLAPI gl_hooks_t gHooksNoContext;
 EGLAPI pthread_key_t gGLWrapperKey = -1;
 
+#if EGL_TRACE
+
+EGLAPI pthread_key_t gGLTraceKey = -1;
+
+// ----------------------------------------------------------------------------
+
+static int gEGLTraceLevel;
+static int gEGLApplicationTraceLevel;
+extern EGLAPI gl_hooks_t gHooksTrace;
+
+static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
+    pthread_setspecific(gGLTraceKey, value);
+}
+
+gl_hooks_t const* getGLTraceThreadSpecific() {
+    return static_cast<gl_hooks_t*>(pthread_getspecific(gGLTraceKey));
+}
+
+static void initEglTraceLevel() {
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.egl.trace", value, "0");
+    int propertyLevel = atoi(value);
+    int applicationLevel = gEGLApplicationTraceLevel;
+    gEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
+}
+
+static void setGLHooksThreadSpecific(gl_hooks_t const *value) {
+    if (gEGLTraceLevel > 0) {
+        setGlTraceThreadSpecific(value);
+        setGlThreadSpecific(&gHooksTrace);
+    } else {
+        setGlThreadSpecific(value);
+    }
+}
+
+/*
+ * Global entry point to allow applications to modify their own trace level.
+ * The effective trace level is the max of this level and the value of debug.egl.trace.
+ */
+extern "C"
+void setGLTraceLevel(int level) {
+    gEGLApplicationTraceLevel = level;
+}
+
+#else
+
+static inline void setGLHooksThreadSpecific(gl_hooks_t const *value) {
+    setGlThreadSpecific(value);
+}
+
+#endif
+
 // ----------------------------------------------------------------------------
 
 static __attribute__((noinline))
@@ -459,13 +511,17 @@
 #if !USE_FAST_TLS_KEY
     pthread_key_create(&gGLWrapperKey, NULL);
 #endif
+#if EGL_TRACE
+    pthread_key_create(&gGLTraceKey, NULL);
+    initEglTraceLevel();
+#endif
     uint32_t addr = (uint32_t)((void*)gl_no_context);
     android_memset32(
             (uint32_t*)(void*)&gHooksNoContext, 
             addr, 
             sizeof(gHooksNoContext));
 
-    setGlThreadSpecific(&gHooksNoContext);
+    setGLHooksThreadSpecific(&gHooksNoContext);
 }
 
 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
@@ -677,9 +733,17 @@
         dp->refs++;
         return EGL_TRUE;
     }
-    
-    setGlThreadSpecific(&gHooksNoContext);
-    
+
+#if EGL_TRACE
+
+    // Called both at early_init time and at this time. (Early_init is pre-zygote, so
+    // the information from that call may be stale.)
+    initEglTraceLevel();
+
+#endif
+
+    setGLHooksThreadSpecific(&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
@@ -1238,11 +1302,11 @@
 
         // cur_c has to be valid here (but could be terminated)
         if (ctx != EGL_NO_CONTEXT) {
-            setGlThreadSpecific(c->cnx->hooks[c->version]);
+            setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
             setContext(ctx);
             _c.acquire();
         } else {
-            setGlThreadSpecific(&gHooksNoContext);
+            setGLHooksThreadSpecific(&gHooksNoContext);
             setContext(EGL_NO_CONTEXT);
         }
         _cur_c.release();
@@ -1434,6 +1498,9 @@
                     // Extensions are independent of the bound context
                     cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
                     cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
+#if EGL_TRACE
+                    gHooksTrace.ext.extensions[slot] =
+#endif
                             cnx->egl.eglGetProcAddress(procname);
                 }
             }
diff --git a/opengl/libs/EGL/trace.cpp b/opengl/libs/EGL/trace.cpp
new file mode 100644
index 0000000..d3e96ba
--- /dev/null
+++ b/opengl/libs/EGL/trace.cpp
@@ -0,0 +1,355 @@
+/*
+ ** Copyright 2010, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#if EGL_TRACE
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <cutils/log.h>
+
+#include "hooks.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+struct GLenumString {
+    GLenum e;
+    const char* s;
+};
+
+#undef GL_ENUM
+#define GL_ENUM(VAL,NAME) {VAL, #NAME},
+
+static GLenumString g_enumnames[] = {
+#include "enums.in"
+};
+#undef GL_ENUM
+
+static int compareGLEnum(const void* a, const void* b) {
+    return ((const GLenumString*) a)->e - ((const GLenumString*) b)->e;
+}
+
+static const char* GLEnumToString(GLenum e) {
+    GLenumString key = {e, ""};
+    const GLenumString* result = (const GLenumString*) bsearch(
+        &key, g_enumnames,
+        sizeof(g_enumnames) / sizeof(g_enumnames[0]),
+        sizeof(g_enumnames[0]), compareGLEnum);
+    if (result) {
+        return result->s;
+    }
+    return NULL;
+}
+
+static const char* GLbooleanToString(GLboolean arg) {
+    return arg ? "GL_TRUE" : "GL_FALSE";
+}
+
+static GLenumString g_bitfieldNames[] = {
+    {0x00004000, "GL_COLOR_BUFFER_BIT"},
+    {0x00000400, "GL_STENCIL_BUFFER_BIT"},
+    {0x00000100, "GL_DEPTH_BUFFER_BIT"}
+};
+
+class StringBuilder {
+    static const int lineSize = 500;
+    char line[lineSize];
+    int line_index;
+public:
+    StringBuilder() {
+        line_index = 0;
+        line[0] = '\0';
+    }
+    void append(const char* fmt, ...) {
+        va_list argp;
+        va_start(argp, fmt);
+        line_index += vsnprintf(line + line_index, lineSize-line_index, fmt, argp);
+        va_end(argp);
+    }
+    const char* getString() {
+        line_index = 0;
+        line[lineSize-1] = '\0';
+        return line;
+    }
+};
+
+
+static void TraceGLShaderSource(GLuint shader, GLsizei count,
+    const GLchar** string, const GLint* length) {
+    LOGD("const char* shaderSrc[] = {");
+    for (GLsizei i = 0; i < count; i++) {
+        const char* comma = i < count-1 ? "," : "";
+        const GLchar* s = string[i];
+        if (length) {
+            GLint len = length[i];
+            LOGD("    \"%*s\"%s", len, s, comma);
+        } else {
+            LOGD("    \"%s\"%s", s, comma);
+        }
+    }
+    LOGD("};");
+    if (length) {
+        LOGD("const GLint* shaderLength[] = {");
+        for (GLsizei i = 0; i < count; i++) {
+            const char* comma = i < count-1 ? "," : "";
+            GLint len = length[i];
+            LOGD("    \"%d\"%s", len, comma);
+        }
+        LOGD("};");
+        LOGD("glShaderSource(%u, %u, shaderSrc, shaderLength);",
+            shader, count);
+    } else {
+        LOGD("glShaderSource(%u, %u, shaderSrc, (const GLint*) 0);",
+            shader, count);
+    }
+}
+
+static void TraceValue(int elementCount, char type,
+        GLsizei chunkCount, GLsizei chunkSize, const void* value) {
+    StringBuilder stringBuilder;
+    GLsizei count = chunkCount * chunkSize;
+    bool isFloat = type == 'f';
+    const char* typeString = isFloat ? "GLfloat" : "GLint";
+    LOGD("const %s value[] = {", typeString);
+    for (GLsizei i = 0; i < count; i++) {
+        StringBuilder builder;
+        builder.append("    ");
+        for (int e = 0; e < elementCount; e++) {
+            const char* comma = ", ";
+            if (e == elementCount-1) {
+                if (i == count - 1) {
+                    comma = "";
+                } else {
+                    comma = ",";
+                }
+            }
+            if (isFloat) {
+                builder.append("%g%s", * (GLfloat*) value, comma);
+                value = (void*) (((GLfloat*) value) + 1);
+            } else {
+                builder.append("%d%s", * (GLint*) value, comma);
+                value = (void*) (((GLint*) value) + 1);
+            }
+        }
+        LOGD("%s", builder.getString());
+        if (chunkSize > 1 && i < count-1
+                && (i % chunkSize) == (chunkSize-1)) {
+            LOGD("%s", ""); // Print a blank line.
+        }
+    }
+    LOGD("};");
+}
+
+static void TraceUniformv(int elementCount, char type,
+        GLuint location, GLsizei count, const void* value) {
+    TraceValue(elementCount, type, count, 1, value);
+    LOGD("glUniform%d%c(%u, %u, value);", elementCount, type, location, count);
+}
+
+static void TraceUniformMatrix(int matrixSideLength,
+        GLuint location, GLsizei count, GLboolean transpose, const void* value) {
+    TraceValue(matrixSideLength, 'f', count, matrixSideLength, value);
+    LOGD("glUniformMatrix%dfv(%u, %u, %s, value);", matrixSideLength, location, count,
+            GLbooleanToString(transpose));
+}
+
+static void TraceGL(const char* name, int numArgs, ...) {
+    va_list argp;
+    va_start(argp, numArgs);
+    int nameLen = strlen(name);
+
+    // glShaderSource
+    if (nameLen == 14 && strcmp(name, "glShaderSource") == 0) {
+        va_arg(argp, const char*);
+        GLuint shader = va_arg(argp, GLuint);
+        va_arg(argp, const char*);
+        GLsizei count = va_arg(argp, GLsizei);
+        va_arg(argp, const char*);
+        const GLchar** string = (const GLchar**) va_arg(argp, void*);
+        va_arg(argp, const char*);
+        const GLint* length = (const GLint*) va_arg(argp, void*);
+        va_end(argp);
+        TraceGLShaderSource(shader, count, string, length);
+        return;
+    }
+
+    // glUniformXXv
+
+    if (nameLen == 12 && strncmp(name, "glUniform", 9) == 0 && name[11] == 'v') {
+        int elementCount = name[9] - '0'; // 1..4
+        char type = name[10]; // 'f' or 'i'
+        va_arg(argp, const char*);
+        GLuint location = va_arg(argp, GLuint);
+        va_arg(argp, const char*);
+        GLsizei count = va_arg(argp, GLsizei);
+        va_arg(argp, const char*);
+        const void* value = (const void*) va_arg(argp, void*);
+        va_end(argp);
+        TraceUniformv(elementCount, type, location, count, value);
+        return;
+    }
+
+    // glUniformMatrixXfv
+
+    if (nameLen == 18 && strncmp(name, "glUniformMatrix", 15) == 0
+            && name[16] == 'f' && name[17] == 'v') {
+        int matrixSideLength = name[15] - '0'; // 2..4
+        va_arg(argp, const char*);
+        GLuint location = va_arg(argp, GLuint);
+        va_arg(argp, const char*);
+        GLsizei count = va_arg(argp, GLsizei);
+        va_arg(argp, const char*);
+        GLboolean transpose = (GLboolean) va_arg(argp, int);
+        va_arg(argp, const char*);
+        const void* value = (const void*) va_arg(argp, void*);
+        va_end(argp);
+        TraceUniformMatrix(matrixSideLength, location, count, transpose, value);
+        return;
+    }
+
+    StringBuilder builder;
+    builder.append("%s(", name);
+    for (int i = 0; i < numArgs; i++) {
+        if (i > 0) {
+            builder.append(", ");
+        }
+        const char* type = va_arg(argp, const char*);
+        bool isPtr = type[strlen(type)-1] == '*'
+            || strcmp(type, "GLeglImageOES") == 0;
+        if (isPtr) {
+            const void* arg = va_arg(argp, const void*);
+            builder.append("(%s) 0x%08x", type, (size_t) arg);
+        } else if (strcmp(type, "GLbitfield") == 0) {
+            size_t arg = va_arg(argp, size_t);
+            bool first = true;
+            for (size_t i = 0; i < sizeof(g_bitfieldNames) / sizeof(g_bitfieldNames[0]); i++) {
+                const GLenumString* b = &g_bitfieldNames[i];
+                if (b->e & arg) {
+                    if (first) {
+                        first = false;
+                    } else {
+                        builder.append(" | ");
+                    }
+                    builder.append("%s", b->s);
+                    arg &= ~b->e;
+                }
+            }
+            if (first || arg != 0) {
+                if (!first) {
+                    builder.append(" | ");
+                }
+                builder.append("0x%08x", arg);
+            }
+        } else if (strcmp(type, "GLboolean") == 0) {
+            GLboolean arg = va_arg(argp, int);
+            builder.append("%s", GLbooleanToString(arg));
+        } else if (strcmp(type, "GLclampf") == 0) {
+            double arg = va_arg(argp, double);
+            builder.append("%g", arg);
+        } else if (strcmp(type, "GLenum") == 0) {
+            GLenum arg = va_arg(argp, int);
+            const char* s = GLEnumToString(arg);
+            if (s) {
+                builder.append("%s", s);
+            } else {
+                builder.append("0x%x", arg);
+            }
+        } else if (strcmp(type, "GLfixed") == 0) {
+            int arg = va_arg(argp, int);
+            builder.append("0x%08x", arg);
+        } else if (strcmp(type, "GLfloat") == 0) {
+            double arg = va_arg(argp, double);
+            builder.append("%g", arg);
+        } else if (strcmp(type, "GLint") == 0) {
+            int arg = va_arg(argp, int);
+            const char* s = NULL;
+            if (strcmp(name, "glTexParameteri") == 0) {
+                s = GLEnumToString(arg);
+            }
+            if (s) {
+                builder.append("%s", s);
+            } else {
+                builder.append("%d", arg);
+            }
+        } else if (strcmp(type, "GLintptr") == 0) {
+            int arg = va_arg(argp, unsigned int);
+            builder.append("%u", arg);
+        } else if (strcmp(type, "GLsizei") == 0) {
+            int arg = va_arg(argp, size_t);
+            builder.append("%u", arg);
+        } else if (strcmp(type, "GLsizeiptr") == 0) {
+            int arg = va_arg(argp, size_t);
+            builder.append("%u", arg);
+        } else if (strcmp(type, "GLuint") == 0) {
+            int arg = va_arg(argp, unsigned int);
+            builder.append("%u", arg);
+        } else {
+            builder.append("/* ??? %s */", type);
+            break;
+        }
+    }
+    builder.append(");");
+    LOGD("%s", builder.getString());
+    va_end(argp);
+}
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
+static void Tracing_ ## _api _args {                                      \
+    TraceGL(#_api, __VA_ARGS__);                                          \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    _c->_api _argList;                                                    \
+}
+
+#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
+static _type Tracing_ ## _api _args {                                     \
+    TraceGL(#_api, __VA_ARGS__);                                          \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    return _c->_api _argList;                                             \
+}
+
+extern "C" {
+#include "../trace.in"
+}
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
+
+EGLAPI gl_hooks_t gHooksTrace = {
+    {
+        #include "entries.in"
+    },
+    {
+        {0}
+    }
+};
+#undef GL_ENTRY
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif // EGL_TRACE
diff --git a/opengl/libs/enums.in b/opengl/libs/enums.in
new file mode 100644
index 0000000..f9752c2
--- /dev/null
+++ b/opengl/libs/enums.in
@@ -0,0 +1,594 @@
+GL_ENUM(0x0000,GL_POINTS)
+GL_ENUM(0x0001,GL_LINES)
+GL_ENUM(0x0002,GL_LINE_LOOP)
+GL_ENUM(0x0003,GL_LINE_STRIP)
+GL_ENUM(0x0004,GL_TRIANGLES)
+GL_ENUM(0x0005,GL_TRIANGLE_STRIP)
+GL_ENUM(0x0006,GL_TRIANGLE_FAN)
+GL_ENUM(0x0104,GL_ADD)
+GL_ENUM(0x0200,GL_NEVER)
+GL_ENUM(0x0201,GL_LESS)
+GL_ENUM(0x0202,GL_EQUAL)
+GL_ENUM(0x0203,GL_LEQUAL)
+GL_ENUM(0x0204,GL_GREATER)
+GL_ENUM(0x0205,GL_NOTEQUAL)
+GL_ENUM(0x0206,GL_GEQUAL)
+GL_ENUM(0x0207,GL_ALWAYS)
+GL_ENUM(0x0300,GL_SRC_COLOR)
+GL_ENUM(0x0301,GL_ONE_MINUS_SRC_COLOR)
+GL_ENUM(0x0302,GL_SRC_ALPHA)
+GL_ENUM(0x0303,GL_ONE_MINUS_SRC_ALPHA)
+GL_ENUM(0x0304,GL_DST_ALPHA)
+GL_ENUM(0x0305,GL_ONE_MINUS_DST_ALPHA)
+GL_ENUM(0x0306,GL_DST_COLOR)
+GL_ENUM(0x0307,GL_ONE_MINUS_DST_COLOR)
+GL_ENUM(0x0308,GL_SRC_ALPHA_SATURATE)
+GL_ENUM(0x0404,GL_FRONT)
+GL_ENUM(0x0405,GL_BACK)
+GL_ENUM(0x0408,GL_FRONT_AND_BACK)
+GL_ENUM(0x0500,GL_INVALID_ENUM)
+GL_ENUM(0x0501,GL_INVALID_VALUE)
+GL_ENUM(0x0502,GL_INVALID_OPERATION)
+GL_ENUM(0x0503,GL_STACK_OVERFLOW)
+GL_ENUM(0x0504,GL_STACK_UNDERFLOW)
+GL_ENUM(0x0505,GL_OUT_OF_MEMORY)
+GL_ENUM(0x0506,GL_INVALID_FRAMEBUFFER_OPERATION_OES)
+GL_ENUM(0x0800,GL_EXP)
+GL_ENUM(0x0801,GL_EXP2)
+GL_ENUM(0x0900,GL_CW)
+GL_ENUM(0x0901,GL_CCW)
+GL_ENUM(0x0B00,GL_CURRENT_COLOR)
+GL_ENUM(0x0B02,GL_CURRENT_NORMAL)
+GL_ENUM(0x0B03,GL_CURRENT_TEXTURE_COORDS)
+GL_ENUM(0x0B10,GL_POINT_SMOOTH)
+GL_ENUM(0x0B11,GL_POINT_SIZE)
+GL_ENUM(0x0B12,GL_SMOOTH_POINT_SIZE_RANGE)
+GL_ENUM(0x0B20,GL_LINE_SMOOTH)
+GL_ENUM(0x0B21,GL_LINE_WIDTH)
+GL_ENUM(0x0B22,GL_SMOOTH_LINE_WIDTH_RANGE)
+GL_ENUM(0x0B44,GL_CULL_FACE)
+GL_ENUM(0x0B45,GL_CULL_FACE_MODE)
+GL_ENUM(0x0B46,GL_FRONT_FACE)
+GL_ENUM(0x0B50,GL_LIGHTING)
+GL_ENUM(0x0B52,GL_LIGHT_MODEL_TWO_SIDE)
+GL_ENUM(0x0B53,GL_LIGHT_MODEL_AMBIENT)
+GL_ENUM(0x0B54,GL_SHADE_MODEL)
+GL_ENUM(0x0B57,GL_COLOR_MATERIAL)
+GL_ENUM(0x0B60,GL_FOG)
+GL_ENUM(0x0B62,GL_FOG_DENSITY)
+GL_ENUM(0x0B63,GL_FOG_START)
+GL_ENUM(0x0B64,GL_FOG_END)
+GL_ENUM(0x0B65,GL_FOG_MODE)
+GL_ENUM(0x0B66,GL_FOG_COLOR)
+GL_ENUM(0x0B70,GL_DEPTH_RANGE)
+GL_ENUM(0x0B71,GL_DEPTH_TEST)
+GL_ENUM(0x0B72,GL_DEPTH_WRITEMASK)
+GL_ENUM(0x0B73,GL_DEPTH_CLEAR_VALUE)
+GL_ENUM(0x0B74,GL_DEPTH_FUNC)
+GL_ENUM(0x0B90,GL_STENCIL_TEST)
+GL_ENUM(0x0B91,GL_STENCIL_CLEAR_VALUE)
+GL_ENUM(0x0B92,GL_STENCIL_FUNC)
+GL_ENUM(0x0B93,GL_STENCIL_VALUE_MASK)
+GL_ENUM(0x0B94,GL_STENCIL_FAIL)
+GL_ENUM(0x0B95,GL_STENCIL_PASS_DEPTH_FAIL)
+GL_ENUM(0x0B96,GL_STENCIL_PASS_DEPTH_PASS)
+GL_ENUM(0x0B97,GL_STENCIL_REF)
+GL_ENUM(0x0B98,GL_STENCIL_WRITEMASK)
+GL_ENUM(0x0BA0,GL_MATRIX_MODE)
+GL_ENUM(0x0BA1,GL_NORMALIZE)
+GL_ENUM(0x0BA2,GL_VIEWPORT)
+GL_ENUM(0x0BA3,GL_MODELVIEW_STACK_DEPTH)
+GL_ENUM(0x0BA4,GL_PROJECTION_STACK_DEPTH)
+GL_ENUM(0x0BA5,GL_TEXTURE_STACK_DEPTH)
+GL_ENUM(0x0BA6,GL_MODELVIEW_MATRIX)
+GL_ENUM(0x0BA7,GL_PROJECTION_MATRIX)
+GL_ENUM(0x0BA8,GL_TEXTURE_MATRIX)
+GL_ENUM(0x0BC0,GL_ALPHA_TEST)
+GL_ENUM(0x0BC1,GL_ALPHA_TEST_FUNC)
+GL_ENUM(0x0BC2,GL_ALPHA_TEST_REF)
+GL_ENUM(0x0BD0,GL_DITHER)
+GL_ENUM(0x0BE0,GL_BLEND_DST)
+GL_ENUM(0x0BE1,GL_BLEND_SRC)
+GL_ENUM(0x0BE2,GL_BLEND)
+GL_ENUM(0x0BF0,GL_LOGIC_OP_MODE)
+GL_ENUM(0x0BF2,GL_COLOR_LOGIC_OP)
+GL_ENUM(0x0C10,GL_SCISSOR_BOX)
+GL_ENUM(0x0C11,GL_SCISSOR_TEST)
+GL_ENUM(0x0C22,GL_COLOR_CLEAR_VALUE)
+GL_ENUM(0x0C23,GL_COLOR_WRITEMASK)
+GL_ENUM(0x0C50,GL_PERSPECTIVE_CORRECTION_HINT)
+GL_ENUM(0x0C51,GL_POINT_SMOOTH_HINT)
+GL_ENUM(0x0C52,GL_LINE_SMOOTH_HINT)
+GL_ENUM(0x0C54,GL_FOG_HINT)
+GL_ENUM(0x0CF5,GL_UNPACK_ALIGNMENT)
+GL_ENUM(0x0D05,GL_PACK_ALIGNMENT)
+GL_ENUM(0x0D1C,GL_ALPHA_SCALE)
+GL_ENUM(0x0D31,GL_MAX_LIGHTS)
+GL_ENUM(0x0D32,GL_MAX_CLIP_PLANES)
+GL_ENUM(0x0D33,GL_MAX_TEXTURE_SIZE)
+GL_ENUM(0x0D36,GL_MAX_MODELVIEW_STACK_DEPTH)
+GL_ENUM(0x0D38,GL_MAX_PROJECTION_STACK_DEPTH)
+GL_ENUM(0x0D39,GL_MAX_TEXTURE_STACK_DEPTH)
+GL_ENUM(0x0D3A,GL_MAX_VIEWPORT_DIMS)
+GL_ENUM(0x0D50,GL_SUBPIXEL_BITS)
+GL_ENUM(0x0D52,GL_RED_BITS)
+GL_ENUM(0x0D53,GL_GREEN_BITS)
+GL_ENUM(0x0D54,GL_BLUE_BITS)
+GL_ENUM(0x0D55,GL_ALPHA_BITS)
+GL_ENUM(0x0D56,GL_DEPTH_BITS)
+GL_ENUM(0x0D57,GL_STENCIL_BITS)
+GL_ENUM(0x0DE1,GL_TEXTURE_2D)
+GL_ENUM(0x1100,GL_DONT_CARE)
+GL_ENUM(0x1101,GL_FASTEST)
+GL_ENUM(0x1102,GL_NICEST)
+GL_ENUM(0x1200,GL_AMBIENT)
+GL_ENUM(0x1201,GL_DIFFUSE)
+GL_ENUM(0x1202,GL_SPECULAR)
+GL_ENUM(0x1203,GL_POSITION)
+GL_ENUM(0x1204,GL_SPOT_DIRECTION)
+GL_ENUM(0x1205,GL_SPOT_EXPONENT)
+GL_ENUM(0x1206,GL_SPOT_CUTOFF)
+GL_ENUM(0x1207,GL_CONSTANT_ATTENUATION)
+GL_ENUM(0x1208,GL_LINEAR_ATTENUATION)
+GL_ENUM(0x1209,GL_QUADRATIC_ATTENUATION)
+GL_ENUM(0x1400,GL_BYTE)
+GL_ENUM(0x1401,GL_UNSIGNED_BYTE)
+GL_ENUM(0x1402,GL_SHORT)
+GL_ENUM(0x1403,GL_UNSIGNED_SHORT)
+GL_ENUM(0x1404,GL_INT)
+GL_ENUM(0x1405,GL_UNSIGNED_INT)
+GL_ENUM(0x1406,GL_FLOAT)
+GL_ENUM(0x140C,GL_FIXED)
+GL_ENUM(0x1500,GL_CLEAR)
+GL_ENUM(0x1501,GL_AND)
+GL_ENUM(0x1502,GL_AND_REVERSE)
+GL_ENUM(0x1503,GL_COPY)
+GL_ENUM(0x1504,GL_AND_INVERTED)
+GL_ENUM(0x1505,GL_NOOP)
+GL_ENUM(0x1506,GL_XOR)
+GL_ENUM(0x1507,GL_OR)
+GL_ENUM(0x1508,GL_NOR)
+GL_ENUM(0x1509,GL_EQUIV)
+GL_ENUM(0x150A,GL_INVERT)
+GL_ENUM(0x150B,GL_OR_REVERSE)
+GL_ENUM(0x150C,GL_COPY_INVERTED)
+GL_ENUM(0x150D,GL_OR_INVERTED)
+GL_ENUM(0x150E,GL_NAND)
+GL_ENUM(0x150F,GL_SET)
+GL_ENUM(0x1600,GL_EMISSION)
+GL_ENUM(0x1601,GL_SHININESS)
+GL_ENUM(0x1602,GL_AMBIENT_AND_DIFFUSE)
+GL_ENUM(0x1700,GL_MODELVIEW)
+GL_ENUM(0x1701,GL_PROJECTION)
+GL_ENUM(0x1702,GL_TEXTURE)
+GL_ENUM(0x1800,GL_COLOR_EXT)
+GL_ENUM(0x1801,GL_DEPTH_EXT)
+GL_ENUM(0x1802,GL_STENCIL_EXT)
+GL_ENUM(0x1901,GL_STENCIL_INDEX)
+GL_ENUM(0x1902,GL_DEPTH_COMPONENT)
+GL_ENUM(0x1906,GL_ALPHA)
+GL_ENUM(0x1907,GL_RGB)
+GL_ENUM(0x1908,GL_RGBA)
+GL_ENUM(0x1909,GL_LUMINANCE)
+GL_ENUM(0x190A,GL_LUMINANCE_ALPHA)
+GL_ENUM(0x1D00,GL_FLAT)
+GL_ENUM(0x1D01,GL_SMOOTH)
+GL_ENUM(0x1E00,GL_KEEP)
+GL_ENUM(0x1E01,GL_REPLACE)
+GL_ENUM(0x1E02,GL_INCR)
+GL_ENUM(0x1E03,GL_DECR)
+GL_ENUM(0x1F00,GL_VENDOR)
+GL_ENUM(0x1F01,GL_RENDERER)
+GL_ENUM(0x1F02,GL_VERSION)
+GL_ENUM(0x1F03,GL_EXTENSIONS)
+GL_ENUM(0x2100,GL_MODULATE)
+GL_ENUM(0x2101,GL_DECAL)
+GL_ENUM(0x2200,GL_TEXTURE_ENV_MODE)
+GL_ENUM(0x2201,GL_TEXTURE_ENV_COLOR)
+GL_ENUM(0x2300,GL_TEXTURE_ENV)
+GL_ENUM(0x2500,GL_TEXTURE_GEN_MODE_OES)
+GL_ENUM(0x2600,GL_NEAREST)
+GL_ENUM(0x2601,GL_LINEAR)
+GL_ENUM(0x2700,GL_NEAREST_MIPMAP_NEAREST)
+GL_ENUM(0x2701,GL_LINEAR_MIPMAP_NEAREST)
+GL_ENUM(0x2702,GL_NEAREST_MIPMAP_LINEAR)
+GL_ENUM(0x2703,GL_LINEAR_MIPMAP_LINEAR)
+GL_ENUM(0x2800,GL_TEXTURE_MAG_FILTER)
+GL_ENUM(0x2801,GL_TEXTURE_MIN_FILTER)
+GL_ENUM(0x2802,GL_TEXTURE_WRAP_S)
+GL_ENUM(0x2803,GL_TEXTURE_WRAP_T)
+GL_ENUM(0x2901,GL_REPEAT)
+GL_ENUM(0x2A00,GL_POLYGON_OFFSET_UNITS)
+GL_ENUM(0x3000,GL_CLIP_PLANE0)
+GL_ENUM(0x3001,GL_CLIP_PLANE1)
+GL_ENUM(0x3002,GL_CLIP_PLANE2)
+GL_ENUM(0x3003,GL_CLIP_PLANE3)
+GL_ENUM(0x3004,GL_CLIP_PLANE4)
+GL_ENUM(0x3005,GL_CLIP_PLANE5)
+GL_ENUM(0x4000,GL_LIGHT0)
+GL_ENUM(0x4001,GL_LIGHT1)
+GL_ENUM(0x4002,GL_LIGHT2)
+GL_ENUM(0x4003,GL_LIGHT3)
+GL_ENUM(0x4004,GL_LIGHT4)
+GL_ENUM(0x4005,GL_LIGHT5)
+GL_ENUM(0x4006,GL_LIGHT6)
+GL_ENUM(0x4007,GL_LIGHT7)
+GL_ENUM(0x8000,GL_COVERAGE_BUFFER_BIT_NV)
+GL_ENUM(0x8001,GL_CONSTANT_COLOR)
+GL_ENUM(0x8002,GL_ONE_MINUS_CONSTANT_COLOR)
+GL_ENUM(0x8003,GL_CONSTANT_ALPHA)
+GL_ENUM(0x8004,GL_ONE_MINUS_CONSTANT_ALPHA)
+GL_ENUM(0x8005,GL_BLEND_COLOR)
+GL_ENUM(0x8006,GL_FUNC_ADD_OES)
+GL_ENUM(0x8007,GL_MIN_EXT)
+GL_ENUM(0x8008,GL_MAX_EXT)
+GL_ENUM(0x8009,GL_BLEND_EQUATION_RGB_OES)
+GL_ENUM(0x800A,GL_FUNC_SUBTRACT_OES)
+GL_ENUM(0x800B,GL_FUNC_REVERSE_SUBTRACT_OES)
+GL_ENUM(0x8033,GL_UNSIGNED_SHORT_4_4_4_4)
+GL_ENUM(0x8034,GL_UNSIGNED_SHORT_5_5_5_1)
+GL_ENUM(0x8037,GL_POLYGON_OFFSET_FILL)
+GL_ENUM(0x8038,GL_POLYGON_OFFSET_FACTOR)
+GL_ENUM(0x803A,GL_RESCALE_NORMAL)
+GL_ENUM(0x8051,GL_RGB8_OES)
+GL_ENUM(0x8056,GL_RGBA4_OES)
+GL_ENUM(0x8057,GL_RGB5_A1_OES)
+GL_ENUM(0x8058,GL_RGBA8_OES)
+GL_ENUM(0x8069,GL_TEXTURE_BINDING_2D)
+GL_ENUM(0x806A,GL_TEXTURE_BINDING_3D_OES)
+GL_ENUM(0x806F,GL_TEXTURE_3D_OES)
+GL_ENUM(0x8072,GL_TEXTURE_WRAP_R_OES)
+GL_ENUM(0x8073,GL_MAX_3D_TEXTURE_SIZE_OES)
+GL_ENUM(0x8074,GL_VERTEX_ARRAY)
+GL_ENUM(0x8075,GL_NORMAL_ARRAY)
+GL_ENUM(0x8076,GL_COLOR_ARRAY)
+GL_ENUM(0x8078,GL_TEXTURE_COORD_ARRAY)
+GL_ENUM(0x807A,GL_VERTEX_ARRAY_SIZE)
+GL_ENUM(0x807B,GL_VERTEX_ARRAY_TYPE)
+GL_ENUM(0x807C,GL_VERTEX_ARRAY_STRIDE)
+GL_ENUM(0x807E,GL_NORMAL_ARRAY_TYPE)
+GL_ENUM(0x807F,GL_NORMAL_ARRAY_STRIDE)
+GL_ENUM(0x8081,GL_COLOR_ARRAY_SIZE)
+GL_ENUM(0x8082,GL_COLOR_ARRAY_TYPE)
+GL_ENUM(0x8083,GL_COLOR_ARRAY_STRIDE)
+GL_ENUM(0x8088,GL_TEXTURE_COORD_ARRAY_SIZE)
+GL_ENUM(0x8089,GL_TEXTURE_COORD_ARRAY_TYPE)
+GL_ENUM(0x808A,GL_TEXTURE_COORD_ARRAY_STRIDE)
+GL_ENUM(0x808E,GL_VERTEX_ARRAY_POINTER)
+GL_ENUM(0x808F,GL_NORMAL_ARRAY_POINTER)
+GL_ENUM(0x8090,GL_COLOR_ARRAY_POINTER)
+GL_ENUM(0x8092,GL_TEXTURE_COORD_ARRAY_POINTER)
+GL_ENUM(0x809D,GL_MULTISAMPLE)
+GL_ENUM(0x809E,GL_SAMPLE_ALPHA_TO_COVERAGE)
+GL_ENUM(0x809F,GL_SAMPLE_ALPHA_TO_ONE)
+GL_ENUM(0x80A0,GL_SAMPLE_COVERAGE)
+GL_ENUM(0x80A8,GL_SAMPLE_BUFFERS)
+GL_ENUM(0x80A9,GL_SAMPLES)
+GL_ENUM(0x80AA,GL_SAMPLE_COVERAGE_VALUE)
+GL_ENUM(0x80AB,GL_SAMPLE_COVERAGE_INVERT)
+GL_ENUM(0x80C8,GL_BLEND_DST_RGB_OES)
+GL_ENUM(0x80C9,GL_BLEND_SRC_RGB_OES)
+GL_ENUM(0x80CA,GL_BLEND_DST_ALPHA_OES)
+GL_ENUM(0x80CB,GL_BLEND_SRC_ALPHA_OES)
+GL_ENUM(0x80E1,GL_BGRA_EXT)
+GL_ENUM(0x8126,GL_POINT_SIZE_MIN)
+GL_ENUM(0x8127,GL_POINT_SIZE_MAX)
+GL_ENUM(0x8128,GL_POINT_FADE_THRESHOLD_SIZE)
+GL_ENUM(0x8129,GL_POINT_DISTANCE_ATTENUATION)
+GL_ENUM(0x812F,GL_CLAMP_TO_EDGE)
+GL_ENUM(0x8191,GL_GENERATE_MIPMAP)
+GL_ENUM(0x8192,GL_GENERATE_MIPMAP_HINT)
+GL_ENUM(0x81A5,GL_DEPTH_COMPONENT16_OES)
+GL_ENUM(0x81A6,GL_DEPTH_COMPONENT24_OES)
+GL_ENUM(0x81A7,GL_DEPTH_COMPONENT32_OES)
+GL_ENUM(0x8363,GL_UNSIGNED_SHORT_5_6_5)
+GL_ENUM(0x8365,GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT)
+GL_ENUM(0x8366,GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)
+GL_ENUM(0x8368,GL_UNSIGNED_INT_2_10_10_10_REV_EXT)
+GL_ENUM(0x8370,GL_MIRRORED_REPEAT_OES)
+GL_ENUM(0x83F0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
+GL_ENUM(0x83F1,GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+GL_ENUM(0x846D,GL_ALIASED_POINT_SIZE_RANGE)
+GL_ENUM(0x846E,GL_ALIASED_LINE_WIDTH_RANGE)
+GL_ENUM(0x84C0,GL_TEXTURE0)
+GL_ENUM(0x84C1,GL_TEXTURE1)
+GL_ENUM(0x84C2,GL_TEXTURE2)
+GL_ENUM(0x84C3,GL_TEXTURE3)
+GL_ENUM(0x84C4,GL_TEXTURE4)
+GL_ENUM(0x84C5,GL_TEXTURE5)
+GL_ENUM(0x84C6,GL_TEXTURE6)
+GL_ENUM(0x84C7,GL_TEXTURE7)
+GL_ENUM(0x84C8,GL_TEXTURE8)
+GL_ENUM(0x84C9,GL_TEXTURE9)
+GL_ENUM(0x84CA,GL_TEXTURE10)
+GL_ENUM(0x84CB,GL_TEXTURE11)
+GL_ENUM(0x84CC,GL_TEXTURE12)
+GL_ENUM(0x84CD,GL_TEXTURE13)
+GL_ENUM(0x84CE,GL_TEXTURE14)
+GL_ENUM(0x84CF,GL_TEXTURE15)
+GL_ENUM(0x84D0,GL_TEXTURE16)
+GL_ENUM(0x84D1,GL_TEXTURE17)
+GL_ENUM(0x84D2,GL_TEXTURE18)
+GL_ENUM(0x84D3,GL_TEXTURE19)
+GL_ENUM(0x84D4,GL_TEXTURE20)
+GL_ENUM(0x84D5,GL_TEXTURE21)
+GL_ENUM(0x84D6,GL_TEXTURE22)
+GL_ENUM(0x84D7,GL_TEXTURE23)
+GL_ENUM(0x84D8,GL_TEXTURE24)
+GL_ENUM(0x84D9,GL_TEXTURE25)
+GL_ENUM(0x84DA,GL_TEXTURE26)
+GL_ENUM(0x84DB,GL_TEXTURE27)
+GL_ENUM(0x84DC,GL_TEXTURE28)
+GL_ENUM(0x84DD,GL_TEXTURE29)
+GL_ENUM(0x84DE,GL_TEXTURE30)
+GL_ENUM(0x84DF,GL_TEXTURE31)
+GL_ENUM(0x84E0,GL_ACTIVE_TEXTURE)
+GL_ENUM(0x84E1,GL_CLIENT_ACTIVE_TEXTURE)
+GL_ENUM(0x84E2,GL_MAX_TEXTURE_UNITS)
+GL_ENUM(0x84E7,GL_SUBTRACT)
+GL_ENUM(0x84E8,GL_MAX_RENDERBUFFER_SIZE_OES)
+GL_ENUM(0x84F2,GL_ALL_COMPLETED_NV)
+GL_ENUM(0x84F3,GL_FENCE_STATUS_NV)
+GL_ENUM(0x84F4,GL_FENCE_CONDITION_NV)
+GL_ENUM(0x84F9,GL_DEPTH_STENCIL_OES)
+GL_ENUM(0x84FA,GL_UNSIGNED_INT_24_8_OES)
+GL_ENUM(0x84FD,GL_MAX_TEXTURE_LOD_BIAS_EXT)
+GL_ENUM(0x84FE,GL_TEXTURE_MAX_ANISOTROPY_EXT)
+GL_ENUM(0x84FF,GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)
+GL_ENUM(0x8500,GL_TEXTURE_FILTER_CONTROL_EXT)
+GL_ENUM(0x8501,GL_TEXTURE_LOD_BIAS_EXT)
+GL_ENUM(0x8507,GL_INCR_WRAP_OES)
+GL_ENUM(0x8508,GL_DECR_WRAP_OES)
+GL_ENUM(0x8511,GL_NORMAL_MAP_OES)
+GL_ENUM(0x8512,GL_REFLECTION_MAP_OES)
+GL_ENUM(0x8513,GL_TEXTURE_CUBE_MAP_OES)
+GL_ENUM(0x8514,GL_TEXTURE_BINDING_CUBE_MAP_OES)
+GL_ENUM(0x8515,GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES)
+GL_ENUM(0x8516,GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES)
+GL_ENUM(0x8517,GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES)
+GL_ENUM(0x8518,GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES)
+GL_ENUM(0x8519,GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES)
+GL_ENUM(0x851A,GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES)
+GL_ENUM(0x851C,GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES)
+GL_ENUM(0x8570,GL_COMBINE)
+GL_ENUM(0x8571,GL_COMBINE_RGB)
+GL_ENUM(0x8572,GL_COMBINE_ALPHA)
+GL_ENUM(0x8573,GL_RGB_SCALE)
+GL_ENUM(0x8574,GL_ADD_SIGNED)
+GL_ENUM(0x8575,GL_INTERPOLATE)
+GL_ENUM(0x8576,GL_CONSTANT)
+GL_ENUM(0x8577,GL_PRIMARY_COLOR)
+GL_ENUM(0x8578,GL_PREVIOUS)
+GL_ENUM(0x8580,GL_SRC0_RGB)
+GL_ENUM(0x8581,GL_SRC1_RGB)
+GL_ENUM(0x8582,GL_SRC2_RGB)
+GL_ENUM(0x8588,GL_SRC0_ALPHA)
+GL_ENUM(0x8589,GL_SRC1_ALPHA)
+GL_ENUM(0x858A,GL_SRC2_ALPHA)
+GL_ENUM(0x8590,GL_OPERAND0_RGB)
+GL_ENUM(0x8591,GL_OPERAND1_RGB)
+GL_ENUM(0x8592,GL_OPERAND2_RGB)
+GL_ENUM(0x8598,GL_OPERAND0_ALPHA)
+GL_ENUM(0x8599,GL_OPERAND1_ALPHA)
+GL_ENUM(0x859A,GL_OPERAND2_ALPHA)
+GL_ENUM(0x85B5,GL_VERTEX_ARRAY_BINDING_OES)
+GL_ENUM(0x8622,GL_VERTEX_ATTRIB_ARRAY_ENABLED)
+GL_ENUM(0x8623,GL_VERTEX_ATTRIB_ARRAY_SIZE)
+GL_ENUM(0x8624,GL_VERTEX_ATTRIB_ARRAY_STRIDE)
+GL_ENUM(0x8625,GL_VERTEX_ATTRIB_ARRAY_TYPE)
+GL_ENUM(0x8626,GL_CURRENT_VERTEX_ATTRIB)
+GL_ENUM(0x8645,GL_VERTEX_ATTRIB_ARRAY_POINTER)
+GL_ENUM(0x86A2,GL_NUM_COMPRESSED_TEXTURE_FORMATS)
+GL_ENUM(0x86A3,GL_COMPRESSED_TEXTURE_FORMATS)
+GL_ENUM(0x86A4,GL_MAX_VERTEX_UNITS_OES)
+GL_ENUM(0x86A9,GL_WEIGHT_ARRAY_TYPE_OES)
+GL_ENUM(0x86AA,GL_WEIGHT_ARRAY_STRIDE_OES)
+GL_ENUM(0x86AB,GL_WEIGHT_ARRAY_SIZE_OES)
+GL_ENUM(0x86AC,GL_WEIGHT_ARRAY_POINTER_OES)
+GL_ENUM(0x86AD,GL_WEIGHT_ARRAY_OES)
+GL_ENUM(0x86AE,GL_DOT3_RGB)
+GL_ENUM(0x86AF,GL_DOT3_RGBA)
+GL_ENUM(0x8740,GL_Z400_BINARY_AMD)
+GL_ENUM(0x8741,GL_PROGRAM_BINARY_LENGTH_OES)
+GL_ENUM(0x8764,GL_BUFFER_SIZE)
+GL_ENUM(0x8765,GL_BUFFER_USAGE)
+GL_ENUM(0x87EE,GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD)
+GL_ENUM(0x87F9,GL_3DC_X_AMD)
+GL_ENUM(0x87FA,GL_3DC_XY_AMD)
+GL_ENUM(0x87FE,GL_NUM_PROGRAM_BINARY_FORMATS_OES)
+GL_ENUM(0x87FF,GL_PROGRAM_BINARY_FORMATS_OES)
+GL_ENUM(0x8800,GL_STENCIL_BACK_FUNC)
+GL_ENUM(0x8801,GL_STENCIL_BACK_FAIL)
+GL_ENUM(0x8802,GL_STENCIL_BACK_PASS_DEPTH_FAIL)
+GL_ENUM(0x8803,GL_STENCIL_BACK_PASS_DEPTH_PASS)
+GL_ENUM(0x8823,GL_WRITEONLY_RENDERING_QCOM)
+GL_ENUM(0x883D,GL_BLEND_EQUATION_ALPHA_OES)
+GL_ENUM(0x8840,GL_MATRIX_PALETTE_OES)
+GL_ENUM(0x8842,GL_MAX_PALETTE_MATRICES_OES)
+GL_ENUM(0x8843,GL_CURRENT_PALETTE_MATRIX_OES)
+GL_ENUM(0x8844,GL_MATRIX_INDEX_ARRAY_OES)
+GL_ENUM(0x8846,GL_MATRIX_INDEX_ARRAY_SIZE_OES)
+GL_ENUM(0x8847,GL_MATRIX_INDEX_ARRAY_TYPE_OES)
+GL_ENUM(0x8848,GL_MATRIX_INDEX_ARRAY_STRIDE_OES)
+GL_ENUM(0x8849,GL_MATRIX_INDEX_ARRAY_POINTER_OES)
+GL_ENUM(0x8861,GL_POINT_SPRITE_OES)
+GL_ENUM(0x8862,GL_COORD_REPLACE_OES)
+GL_ENUM(0x8869,GL_MAX_VERTEX_ATTRIBS)
+GL_ENUM(0x886A,GL_VERTEX_ATTRIB_ARRAY_NORMALIZED)
+GL_ENUM(0x8872,GL_MAX_TEXTURE_IMAGE_UNITS)
+GL_ENUM(0x8892,GL_ARRAY_BUFFER)
+GL_ENUM(0x8893,GL_ELEMENT_ARRAY_BUFFER)
+GL_ENUM(0x8894,GL_ARRAY_BUFFER_BINDING)
+GL_ENUM(0x8895,GL_ELEMENT_ARRAY_BUFFER_BINDING)
+GL_ENUM(0x8896,GL_VERTEX_ARRAY_BUFFER_BINDING)
+GL_ENUM(0x8897,GL_NORMAL_ARRAY_BUFFER_BINDING)
+GL_ENUM(0x8898,GL_COLOR_ARRAY_BUFFER_BINDING)
+GL_ENUM(0x889A,GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING)
+GL_ENUM(0x889E,GL_WEIGHT_ARRAY_BUFFER_BINDING_OES)
+GL_ENUM(0x889F,GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)
+GL_ENUM(0x88B9,GL_WRITE_ONLY_OES)
+GL_ENUM(0x88BB,GL_BUFFER_ACCESS_OES)
+GL_ENUM(0x88BC,GL_BUFFER_MAPPED_OES)
+GL_ENUM(0x88BD,GL_BUFFER_MAP_POINTER_OES)
+GL_ENUM(0x88E0,GL_STREAM_DRAW)
+GL_ENUM(0x88E4,GL_STATIC_DRAW)
+GL_ENUM(0x88E8,GL_DYNAMIC_DRAW)
+GL_ENUM(0x88F0,GL_DEPTH24_STENCIL8_OES)
+GL_ENUM(0x898A,GL_POINT_SIZE_ARRAY_TYPE_OES)
+GL_ENUM(0x898B,GL_POINT_SIZE_ARRAY_STRIDE_OES)
+GL_ENUM(0x898C,GL_POINT_SIZE_ARRAY_POINTER_OES)
+GL_ENUM(0x898D,GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES)
+GL_ENUM(0x898E,GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES)
+GL_ENUM(0x898F,GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES)
+GL_ENUM(0x8B30,GL_FRAGMENT_SHADER)
+GL_ENUM(0x8B31,GL_VERTEX_SHADER)
+GL_ENUM(0x8B4C,GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
+GL_ENUM(0x8B4D,GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
+GL_ENUM(0x8B4F,GL_SHADER_TYPE)
+GL_ENUM(0x8B50,GL_FLOAT_VEC2)
+GL_ENUM(0x8B51,GL_FLOAT_VEC3)
+GL_ENUM(0x8B52,GL_FLOAT_VEC4)
+GL_ENUM(0x8B53,GL_INT_VEC2)
+GL_ENUM(0x8B54,GL_INT_VEC3)
+GL_ENUM(0x8B55,GL_INT_VEC4)
+GL_ENUM(0x8B56,GL_BOOL)
+GL_ENUM(0x8B57,GL_BOOL_VEC2)
+GL_ENUM(0x8B58,GL_BOOL_VEC3)
+GL_ENUM(0x8B59,GL_BOOL_VEC4)
+GL_ENUM(0x8B5A,GL_FLOAT_MAT2)
+GL_ENUM(0x8B5B,GL_FLOAT_MAT3)
+GL_ENUM(0x8B5C,GL_FLOAT_MAT4)
+GL_ENUM(0x8B5E,GL_SAMPLER_2D)
+GL_ENUM(0x8B5F,GL_SAMPLER_3D_OES)
+GL_ENUM(0x8B60,GL_SAMPLER_CUBE)
+GL_ENUM(0x8B80,GL_DELETE_STATUS)
+GL_ENUM(0x8B81,GL_COMPILE_STATUS)
+GL_ENUM(0x8B82,GL_LINK_STATUS)
+GL_ENUM(0x8B83,GL_VALIDATE_STATUS)
+GL_ENUM(0x8B84,GL_INFO_LOG_LENGTH)
+GL_ENUM(0x8B85,GL_ATTACHED_SHADERS)
+GL_ENUM(0x8B86,GL_ACTIVE_UNIFORMS)
+GL_ENUM(0x8B87,GL_ACTIVE_UNIFORM_MAX_LENGTH)
+GL_ENUM(0x8B88,GL_SHADER_SOURCE_LENGTH)
+GL_ENUM(0x8B89,GL_ACTIVE_ATTRIBUTES)
+GL_ENUM(0x8B8A,GL_ACTIVE_ATTRIBUTE_MAX_LENGTH)
+GL_ENUM(0x8B8B,GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES)
+GL_ENUM(0x8B8C,GL_SHADING_LANGUAGE_VERSION)
+GL_ENUM(0x8B8D,GL_CURRENT_PROGRAM)
+GL_ENUM(0x8B90,GL_PALETTE4_RGB8_OES)
+GL_ENUM(0x8B91,GL_PALETTE4_RGBA8_OES)
+GL_ENUM(0x8B92,GL_PALETTE4_R5_G6_B5_OES)
+GL_ENUM(0x8B93,GL_PALETTE4_RGBA4_OES)
+GL_ENUM(0x8B94,GL_PALETTE4_RGB5_A1_OES)
+GL_ENUM(0x8B95,GL_PALETTE8_RGB8_OES)
+GL_ENUM(0x8B96,GL_PALETTE8_RGBA8_OES)
+GL_ENUM(0x8B97,GL_PALETTE8_R5_G6_B5_OES)
+GL_ENUM(0x8B98,GL_PALETTE8_RGBA4_OES)
+GL_ENUM(0x8B99,GL_PALETTE8_RGB5_A1_OES)
+GL_ENUM(0x8B9A,GL_IMPLEMENTATION_COLOR_READ_TYPE_OES)
+GL_ENUM(0x8B9B,GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES)
+GL_ENUM(0x8B9C,GL_POINT_SIZE_ARRAY_OES)
+GL_ENUM(0x8B9D,GL_TEXTURE_CROP_RECT_OES)
+GL_ENUM(0x8B9E,GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES)
+GL_ENUM(0x8B9F,GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES)
+GL_ENUM(0x8BC0,GL_COUNTER_TYPE_AMD)
+GL_ENUM(0x8BC1,GL_COUNTER_RANGE_AMD)
+GL_ENUM(0x8BC2,GL_UNSIGNED_INT64_AMD)
+GL_ENUM(0x8BC3,GL_PERCENTAGE_AMD)
+GL_ENUM(0x8BC4,GL_PERFMON_RESULT_AVAILABLE_AMD)
+GL_ENUM(0x8BC5,GL_PERFMON_RESULT_SIZE_AMD)
+GL_ENUM(0x8BC6,GL_PERFMON_RESULT_AMD)
+GL_ENUM(0x8BD2,GL_TEXTURE_WIDTH_QCOM)
+GL_ENUM(0x8BD3,GL_TEXTURE_HEIGHT_QCOM)
+GL_ENUM(0x8BD4,GL_TEXTURE_DEPTH_QCOM)
+GL_ENUM(0x8BD5,GL_TEXTURE_INTERNAL_FORMAT_QCOM)
+GL_ENUM(0x8BD6,GL_TEXTURE_FORMAT_QCOM)
+GL_ENUM(0x8BD7,GL_TEXTURE_TYPE_QCOM)
+GL_ENUM(0x8BD8,GL_TEXTURE_IMAGE_VALID_QCOM)
+GL_ENUM(0x8BD9,GL_TEXTURE_NUM_LEVELS_QCOM)
+GL_ENUM(0x8BDA,GL_TEXTURE_TARGET_QCOM)
+GL_ENUM(0x8BDB,GL_TEXTURE_OBJECT_VALID_QCOM)
+GL_ENUM(0x8BDC,GL_STATE_RESTORE)
+GL_ENUM(0x8C00,GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG)
+GL_ENUM(0x8C01,GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG)
+GL_ENUM(0x8C02,GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG)
+GL_ENUM(0x8C03,GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG)
+GL_ENUM(0x8C04,GL_MODULATE_COLOR_IMG)
+GL_ENUM(0x8C05,GL_RECIP_ADD_SIGNED_ALPHA_IMG)
+GL_ENUM(0x8C06,GL_TEXTURE_ALPHA_MODULATE_IMG)
+GL_ENUM(0x8C07,GL_FACTOR_ALPHA_MODULATE_IMG)
+GL_ENUM(0x8C08,GL_FRAGMENT_ALPHA_MODULATE_IMG)
+GL_ENUM(0x8C09,GL_ADD_BLEND_IMG)
+GL_ENUM(0x8C0A,GL_SGX_BINARY_IMG)
+GL_ENUM(0x8C92,GL_ATC_RGB_AMD)
+GL_ENUM(0x8C93,GL_ATC_RGBA_EXPLICIT_ALPHA_AMD)
+GL_ENUM(0x8CA3,GL_STENCIL_BACK_REF)
+GL_ENUM(0x8CA4,GL_STENCIL_BACK_VALUE_MASK)
+GL_ENUM(0x8CA5,GL_STENCIL_BACK_WRITEMASK)
+GL_ENUM(0x8CA6,GL_FRAMEBUFFER_BINDING_OES)
+GL_ENUM(0x8CA7,GL_RENDERBUFFER_BINDING_OES)
+GL_ENUM(0x8CD0,GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES)
+GL_ENUM(0x8CD1,GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES)
+GL_ENUM(0x8CD2,GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES)
+GL_ENUM(0x8CD3,GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES)
+GL_ENUM(0x8CD4,GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES)
+GL_ENUM(0x8CD5,GL_FRAMEBUFFER_COMPLETE_OES)
+GL_ENUM(0x8CD6,GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES)
+GL_ENUM(0x8CD7,GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES)
+GL_ENUM(0x8CD9,GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES)
+GL_ENUM(0x8CDA,GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES)
+GL_ENUM(0x8CDD,GL_FRAMEBUFFER_UNSUPPORTED_OES)
+GL_ENUM(0x8CE0,GL_COLOR_ATTACHMENT0_OES)
+GL_ENUM(0x8D00,GL_DEPTH_ATTACHMENT_OES)
+GL_ENUM(0x8D20,GL_STENCIL_ATTACHMENT_OES)
+GL_ENUM(0x8D40,GL_FRAMEBUFFER_OES)
+GL_ENUM(0x8D41,GL_RENDERBUFFER_OES)
+GL_ENUM(0x8D42,GL_RENDERBUFFER_WIDTH_OES)
+GL_ENUM(0x8D43,GL_RENDERBUFFER_HEIGHT_OES)
+GL_ENUM(0x8D44,GL_RENDERBUFFER_INTERNAL_FORMAT_OES)
+GL_ENUM(0x8D46,GL_STENCIL_INDEX1_OES)
+GL_ENUM(0x8D47,GL_STENCIL_INDEX4_OES)
+GL_ENUM(0x8D48,GL_STENCIL_INDEX8_OES)
+GL_ENUM(0x8D50,GL_RENDERBUFFER_RED_SIZE_OES)
+GL_ENUM(0x8D51,GL_RENDERBUFFER_GREEN_SIZE_OES)
+GL_ENUM(0x8D52,GL_RENDERBUFFER_BLUE_SIZE_OES)
+GL_ENUM(0x8D53,GL_RENDERBUFFER_ALPHA_SIZE_OES)
+GL_ENUM(0x8D54,GL_RENDERBUFFER_DEPTH_SIZE_OES)
+GL_ENUM(0x8D55,GL_RENDERBUFFER_STENCIL_SIZE_OES)
+GL_ENUM(0x8D60,GL_TEXTURE_GEN_STR_OES)
+GL_ENUM(0x8D61,GL_HALF_FLOAT_OES)
+GL_ENUM(0x8D62,GL_RGB565_OES)
+GL_ENUM(0x8D64,GL_ETC1_RGB8_OES)
+GL_ENUM(0x8D65,GL_TEXTURE_EXTERNAL_OES)
+GL_ENUM(0x8D66,GL_SAMPLER_EXTERNAL_OES)
+GL_ENUM(0x8D67,GL_TEXTURE_BINDING_EXTERNAL_OES)
+GL_ENUM(0x8D68,GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES)
+GL_ENUM(0x8DF0,GL_LOW_FLOAT)
+GL_ENUM(0x8DF1,GL_MEDIUM_FLOAT)
+GL_ENUM(0x8DF2,GL_HIGH_FLOAT)
+GL_ENUM(0x8DF3,GL_LOW_INT)
+GL_ENUM(0x8DF4,GL_MEDIUM_INT)
+GL_ENUM(0x8DF5,GL_HIGH_INT)
+GL_ENUM(0x8DF6,GL_UNSIGNED_INT_10_10_10_2_OES)
+GL_ENUM(0x8DF7,GL_INT_10_10_10_2_OES)
+GL_ENUM(0x8DF8,GL_SHADER_BINARY_FORMATS)
+GL_ENUM(0x8DF9,GL_NUM_SHADER_BINARY_FORMATS)
+GL_ENUM(0x8DFA,GL_SHADER_COMPILER)
+GL_ENUM(0x8DFB,GL_MAX_VERTEX_UNIFORM_VECTORS)
+GL_ENUM(0x8DFC,GL_MAX_VARYING_VECTORS)
+GL_ENUM(0x8DFD,GL_MAX_FRAGMENT_UNIFORM_VECTORS)
+GL_ENUM(0x8E2C,GL_DEPTH_COMPONENT16_NONLINEAR_NV)
+GL_ENUM(0x8ED0,GL_COVERAGE_COMPONENT_NV)
+GL_ENUM(0x8ED1,GL_COVERAGE_COMPONENT4_NV)
+GL_ENUM(0x8ED2,GL_COVERAGE_ATTACHMENT_NV)
+GL_ENUM(0x8ED3,GL_COVERAGE_BUFFERS_NV)
+GL_ENUM(0x8ED4,GL_COVERAGE_SAMPLES_NV)
+GL_ENUM(0x8ED5,GL_COVERAGE_ALL_FRAGMENTS_NV)
+GL_ENUM(0x8ED6,GL_COVERAGE_EDGE_FRAGMENTS_NV)
+GL_ENUM(0x8ED7,GL_COVERAGE_AUTOMATIC_NV)
+GL_ENUM(0x8FA0,GL_PERFMON_GLOBAL_MODE_QCOM)
+GL_ENUM(0x9130,GL_SGX_PROGRAM_BINARY_IMG)
+GL_ENUM(0x9133,GL_RENDERBUFFER_SAMPLES_IMG)
+GL_ENUM(0x9134,GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG)
+GL_ENUM(0x9135,GL_MAX_SAMPLES_IMG)
+GL_ENUM(0x9136,GL_TEXTURE_SAMPLES_IMG)
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 1ab58cc..812e26d 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -141,6 +141,11 @@
 
 #endif
 
+#if EGL_TRACE
+
+extern gl_hooks_t const* getGLTraceThreadSpecific();
+
+#endif
 
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles
index 120cb4b..50bbf08 100755
--- a/opengl/libs/tools/genfiles
+++ b/opengl/libs/tools/genfiles
@@ -31,3 +31,14 @@
         | sort -t, -k2 \
         | awk -F, '!_[$2]++' \
             > ../entries.in
+
+./gltracegen ../entries.in >../trace.in
+
+cat ../../include/GLES/gl.h \
+    ../../include/GLES/glext.h \
+    ../../include/GLES2/gl2.h \
+    ../../include/GLES2/gl2ext.h \
+        | ./glenumsgen \
+        | sort \
+        > ../enums.in
+
diff --git a/opengl/libs/tools/glenumsgen b/opengl/libs/tools/glenumsgen
new file mode 100755
index 0000000..2ae5fbf
--- /dev/null
+++ b/opengl/libs/tools/glenumsgen
@@ -0,0 +1,38 @@
+#! /usr/bin/perl
+#
+# Copyright (C) 2010 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.
+
+use strict;
+
+my %enumHash = ();
+
+while (my $line = <STDIN>) {
+  next if $line =~ /^\//;
+  # Skip bitfield definitions.
+  next if $line =~ /_BIT(\d+_|\s+)/;
+  if ($line !~ /^#define\s+(\S+)\s+(0x\S+)/) {
+    next;
+  }
+  my $enumName = $1;
+  my $enumValue = $2;
+  next if exists($enumHash { $enumValue });
+  $enumHash { $enumValue } = $enumName;
+  printf("GL_ENUM(%s,%s)\n", $enumValue, $enumName);
+}
+
+
+
+
+
diff --git a/opengl/libs/tools/gltracegen b/opengl/libs/tools/gltracegen
new file mode 100755
index 0000000..da42653
--- /dev/null
+++ b/opengl/libs/tools/gltracegen
@@ -0,0 +1,95 @@
+#! /usr/bin/perl
+#
+# Copyright (C) 2010 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.
+
+use strict;
+
+sub rtrim($)
+{
+    my $string = shift;
+    $string =~ s/\s+$//;
+    return $string;
+}
+
+while (my $line = <>) {
+  next if $line =~ /^\//;
+  next if $line =~ /^#/;
+  next if $line =~ /^\s*$/;
+  if ($line !~ /^GL_ENTRY\(([^,]+), ([^,]+), ([^\)]+)\)/) {
+    next;
+  }
+  my $type = $1;
+  my $name = $2;
+  my $args = $3;
+  
+  my @args = split ',', $args;
+  my $len = scalar(@args);
+  my $nonVoidArgLen = 0;
+  for (my $num = 0; $num < $len; $num++) {
+    if ($args[$num] ne "void") {
+      $nonVoidArgLen++;
+    }
+  }
+  if ($type eq "void") {
+    printf("TRACE_GL_VOID(");
+  } else {
+    printf("TRACE_GL(%s, ", $type);
+  }
+  
+  printf("%s, (%s), (", $name, $args);
+    for (my $num = 0; $num < $len; $num++) {
+    if ($args[$num] ne "void") {
+      if ($num > 0) {
+        print ", ";
+      }
+      #
+      # extract the name from the parameter
+      # type name
+      # const type *name
+      # type *name
+      # type name[4]
+      #
+      if ($args[$num] =~ /(\S+\s)+\**\s*([\w]+)/) {
+        printf("%s", $2);
+      }
+    }
+  }
+  printf("), %d", $nonVoidArgLen);
+  for (my $num = 0; $num < $len; $num++) {
+    if ($args[$num] ne "void") {
+      #
+      # extract the name from the parameter
+      # type name
+      # const type *name
+      # type *name
+      # type name[4]
+      #
+      my $arg = $args[$num];
+      if ($arg =~ /(\S+\s)+\**\s*([\w]+)/) {
+        my $name = $2;
+        if ($arg =~ /((const )*(\S+\s)+\**)\s*([\w]+)/) {
+          my $type = rtrim($1);
+          printf(", \"%s\", %s", $type, $name);
+        }
+      }
+    }
+  }
+  printf(")\n");
+}
+
+
+
+
+
diff --git a/opengl/libs/trace.in b/opengl/libs/trace.in
new file mode 100644
index 0000000..3d492af
--- /dev/null
+++ b/opengl/libs/trace.in
@@ -0,0 +1,376 @@
+TRACE_GL_VOID(glActiveTexture, (GLenum texture), (texture), 1, "GLenum", texture)
+TRACE_GL_VOID(glAlphaFunc, (GLenum func, GLclampf ref), (func, ref), 2, "GLenum", func, "GLclampf", ref)
+TRACE_GL_VOID(glAlphaFuncx, (GLenum func, GLclampx ref), (func, ref), 2, "GLenum", func, "GLclampx", ref)
+TRACE_GL_VOID(glAlphaFuncxOES, (GLenum func, GLclampx ref), (func, ref), 2, "GLenum", func, "GLclampx", ref)
+TRACE_GL_VOID(glAttachShader, (GLuint program, GLuint shader), (program, shader), 2, "GLuint", program, "GLuint", shader)
+TRACE_GL_VOID(glBeginPerfMonitorAMD, (GLuint monitor), (monitor), 1, "GLuint", monitor)
+TRACE_GL_VOID(glBindAttribLocation, (GLuint program, GLuint index, const GLchar* name), (program, index, name), 3, "GLuint", program, "GLuint", index, "const GLchar*", name)
+TRACE_GL_VOID(glBindBuffer, (GLenum target, GLuint buffer), (target, buffer), 2, "GLenum", target, "GLuint", buffer)
+TRACE_GL_VOID(glBindFramebuffer, (GLenum target, GLuint framebuffer), (target, framebuffer), 2, "GLenum", target, "GLuint", framebuffer)
+TRACE_GL_VOID(glBindFramebufferOES, (GLenum target, GLuint framebuffer), (target, framebuffer), 2, "GLenum", target, "GLuint", framebuffer)
+TRACE_GL_VOID(glBindRenderbuffer, (GLenum target, GLuint renderbuffer), (target, renderbuffer), 2, "GLenum", target, "GLuint", renderbuffer)
+TRACE_GL_VOID(glBindRenderbufferOES, (GLenum target, GLuint renderbuffer), (target, renderbuffer), 2, "GLenum", target, "GLuint", renderbuffer)
+TRACE_GL_VOID(glBindTexture, (GLenum target, GLuint texture), (target, texture), 2, "GLenum", target, "GLuint", texture)
+TRACE_GL_VOID(glBindVertexArrayOES, (GLuint array), (array), 1, "GLuint", array)
+TRACE_GL_VOID(glBlendColor, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha), (red, green, blue, alpha), 4, "GLclampf", red, "GLclampf", green, "GLclampf", blue, "GLclampf", alpha)
+TRACE_GL_VOID(glBlendEquation, ( GLenum mode ), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glBlendEquationOES, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glBlendEquationSeparate, (GLenum modeRGB, GLenum modeAlpha), (modeRGB, modeAlpha), 2, "GLenum", modeRGB, "GLenum", modeAlpha)
+TRACE_GL_VOID(glBlendEquationSeparateOES, (GLenum modeRGB, GLenum modeAlpha), (modeRGB, modeAlpha), 2, "GLenum", modeRGB, "GLenum", modeAlpha)
+TRACE_GL_VOID(glBlendFunc, (GLenum sfactor, GLenum dfactor), (sfactor, dfactor), 2, "GLenum", sfactor, "GLenum", dfactor)
+TRACE_GL_VOID(glBlendFuncSeparate, (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha), (srcRGB, dstRGB, srcAlpha, dstAlpha), 4, "GLenum", srcRGB, "GLenum", dstRGB, "GLenum", srcAlpha, "GLenum", dstAlpha)
+TRACE_GL_VOID(glBlendFuncSeparateOES, (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha), (srcRGB, dstRGB, srcAlpha, dstAlpha), 4, "GLenum", srcRGB, "GLenum", dstRGB, "GLenum", srcAlpha, "GLenum", dstAlpha)
+TRACE_GL_VOID(glBufferData, (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage), (target, size, data, usage), 4, "GLenum", target, "GLsizeiptr", size, "const GLvoid *", data, "GLenum", usage)
+TRACE_GL_VOID(glBufferSubData, (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data), (target, offset, size, data), 4, "GLenum", target, "GLintptr", offset, "GLsizeiptr", size, "const GLvoid *", data)
+TRACE_GL(GLenum, glCheckFramebufferStatus, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL(GLenum, glCheckFramebufferStatusOES, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL_VOID(glClear, (GLbitfield mask), (mask), 1, "GLbitfield", mask)
+TRACE_GL_VOID(glClearColor, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha), (red, green, blue, alpha), 4, "GLclampf", red, "GLclampf", green, "GLclampf", blue, "GLclampf", alpha)
+TRACE_GL_VOID(glClearColorx, (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha), (red, green, blue, alpha), 4, "GLclampx", red, "GLclampx", green, "GLclampx", blue, "GLclampx", alpha)
+TRACE_GL_VOID(glClearColorxOES, (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha), (red, green, blue, alpha), 4, "GLclampx", red, "GLclampx", green, "GLclampx", blue, "GLclampx", alpha)
+TRACE_GL_VOID(glClearDepthf, (GLclampf depth), (depth), 1, "GLclampf", depth)
+TRACE_GL_VOID(glClearDepthfOES, (GLclampf depth), (depth), 1, "GLclampf", depth)
+TRACE_GL_VOID(glClearDepthx, (GLclampx depth), (depth), 1, "GLclampx", depth)
+TRACE_GL_VOID(glClearDepthxOES, (GLclampx depth), (depth), 1, "GLclampx", depth)
+TRACE_GL_VOID(glClearStencil, (GLint s), (s), 1, "GLint", s)
+TRACE_GL_VOID(glClientActiveTexture, (GLenum texture), (texture), 1, "GLenum", texture)
+TRACE_GL_VOID(glClipPlanef, (GLenum plane, const GLfloat *equation), (plane, equation), 2, "GLenum", plane, "const GLfloat *", equation)
+TRACE_GL_VOID(glClipPlanefIMG, (GLenum p, const GLfloat *eqn), (p, eqn), 2, "GLenum", p, "const GLfloat *", eqn)
+TRACE_GL_VOID(glClipPlanefOES, (GLenum plane, const GLfloat *equation), (plane, equation), 2, "GLenum", plane, "const GLfloat *", equation)
+TRACE_GL_VOID(glClipPlanex, (GLenum plane, const GLfixed *equation), (plane, equation), 2, "GLenum", plane, "const GLfixed *", equation)
+TRACE_GL_VOID(glClipPlanexIMG, (GLenum p, const GLfixed *eqn), (p, eqn), 2, "GLenum", p, "const GLfixed *", eqn)
+TRACE_GL_VOID(glClipPlanexOES, (GLenum plane, const GLfixed *equation), (plane, equation), 2, "GLenum", plane, "const GLfixed *", equation)
+TRACE_GL_VOID(glColor4f, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha), (red, green, blue, alpha), 4, "GLfloat", red, "GLfloat", green, "GLfloat", blue, "GLfloat", alpha)
+TRACE_GL_VOID(glColor4ub, (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha), (red, green, blue, alpha), 4, "GLubyte", red, "GLubyte", green, "GLubyte", blue, "GLubyte", alpha)
+TRACE_GL_VOID(glColor4x, (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha), (red, green, blue, alpha), 4, "GLfixed", red, "GLfixed", green, "GLfixed", blue, "GLfixed", alpha)
+TRACE_GL_VOID(glColor4xOES, (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha), (red, green, blue, alpha), 4, "GLfixed", red, "GLfixed", green, "GLfixed", blue, "GLfixed", alpha)
+TRACE_GL_VOID(glColorMask, (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha), (red, green, blue, alpha), 4, "GLboolean", red, "GLboolean", green, "GLboolean", blue, "GLboolean", alpha)
+TRACE_GL_VOID(glColorPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glCompileShader, (GLuint shader), (shader), 1, "GLuint", shader)
+TRACE_GL_VOID(glCompressedTexImage2D, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data), (target, level, internalformat, width, height, border, imageSize, data), 8, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLint", border, "GLsizei", imageSize, "const GLvoid *", data)
+TRACE_GL_VOID(glCompressedTexImage3DOES, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data), (target, level, internalformat, width, height, depth, border, imageSize, data), 9, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLint", border, "GLsizei", imageSize, "const GLvoid*", data)
+TRACE_GL_VOID(glCompressedTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data), (target, level, xoffset, yoffset, width, height, format, imageSize, data), 9, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLsizei", width, "GLsizei", height, "GLenum", format, "GLsizei", imageSize, "const GLvoid *", data)
+TRACE_GL_VOID(glCompressedTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLsizei", imageSize, "const GLvoid*", data)
+TRACE_GL_VOID(glCopyTexImage2D, (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border), (target, level, internalformat, x, y, width, height, border), 8, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height, "GLint", border)
+TRACE_GL_VOID(glCopyTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height), (target, level, xoffset, yoffset, x, y, width, height), 8, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glCopyTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height), (target, level, xoffset, yoffset, zoffset, x, y, width, height), 9, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glCoverageMaskNV, (GLboolean mask), (mask), 1, "GLboolean", mask)
+TRACE_GL_VOID(glCoverageOperationNV, (GLenum operation), (operation), 1, "GLenum", operation)
+TRACE_GL(GLuint, glCreateProgram, (void), (), 0)
+TRACE_GL(GLuint, glCreateShader, (GLenum type), (type), 1, "GLenum", type)
+TRACE_GL_VOID(glCullFace, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glCurrentPaletteMatrixOES, (GLuint matrixpaletteindex), (matrixpaletteindex), 1, "GLuint", matrixpaletteindex)
+TRACE_GL_VOID(glDeleteBuffers, (GLsizei n, const GLuint *buffers), (n, buffers), 2, "GLsizei", n, "const GLuint *", buffers)
+TRACE_GL_VOID(glDeleteFencesNV, (GLsizei n, const GLuint *fences), (n, fences), 2, "GLsizei", n, "const GLuint *", fences)
+TRACE_GL_VOID(glDeleteFramebuffers, (GLsizei n, const GLuint* framebuffers), (n, framebuffers), 2, "GLsizei", n, "const GLuint*", framebuffers)
+TRACE_GL_VOID(glDeleteFramebuffersOES, (GLsizei n, const GLuint* framebuffers), (n, framebuffers), 2, "GLsizei", n, "const GLuint*", framebuffers)
+TRACE_GL_VOID(glDeletePerfMonitorsAMD, (GLsizei n, GLuint *monitors), (n, monitors), 2, "GLsizei", n, "GLuint *", monitors)
+TRACE_GL_VOID(glDeleteProgram, (GLuint program), (program), 1, "GLuint", program)
+TRACE_GL_VOID(glDeleteRenderbuffers, (GLsizei n, const GLuint* renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "const GLuint*", renderbuffers)
+TRACE_GL_VOID(glDeleteRenderbuffersOES, (GLsizei n, const GLuint* renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "const GLuint*", renderbuffers)
+TRACE_GL_VOID(glDeleteShader, (GLuint shader), (shader), 1, "GLuint", shader)
+TRACE_GL_VOID(glDeleteTextures, (GLsizei n, const GLuint *textures), (n, textures), 2, "GLsizei", n, "const GLuint *", textures)
+TRACE_GL_VOID(glDeleteVertexArraysOES, (GLsizei n, const GLuint *arrays), (n, arrays), 2, "GLsizei", n, "const GLuint *", arrays)
+TRACE_GL_VOID(glDepthFunc, (GLenum func), (func), 1, "GLenum", func)
+TRACE_GL_VOID(glDepthMask, (GLboolean flag), (flag), 1, "GLboolean", flag)
+TRACE_GL_VOID(glDepthRangef, (GLclampf zNear, GLclampf zFar), (zNear, zFar), 2, "GLclampf", zNear, "GLclampf", zFar)
+TRACE_GL_VOID(glDepthRangefOES, (GLclampf zNear, GLclampf zFar), (zNear, zFar), 2, "GLclampf", zNear, "GLclampf", zFar)
+TRACE_GL_VOID(glDepthRangex, (GLclampx zNear, GLclampx zFar), (zNear, zFar), 2, "GLclampx", zNear, "GLclampx", zFar)
+TRACE_GL_VOID(glDepthRangexOES, (GLclampx zNear, GLclampx zFar), (zNear, zFar), 2, "GLclampx", zNear, "GLclampx", zFar)
+TRACE_GL_VOID(glDetachShader, (GLuint program, GLuint shader), (program, shader), 2, "GLuint", program, "GLuint", shader)
+TRACE_GL_VOID(glDisable, (GLenum cap), (cap), 1, "GLenum", cap)
+TRACE_GL_VOID(glDisableClientState, (GLenum array), (array), 1, "GLenum", array)
+TRACE_GL_VOID(glDisableDriverControlQCOM, (GLuint driverControl), (driverControl), 1, "GLuint", driverControl)
+TRACE_GL_VOID(glDisableVertexAttribArray, (GLuint index), (index), 1, "GLuint", index)
+TRACE_GL_VOID(glDiscardFramebufferEXT, (GLenum target, GLsizei numAttachments, const GLenum *attachments), (target, numAttachments, attachments), 3, "GLenum", target, "GLsizei", numAttachments, "const GLenum *", attachments)
+TRACE_GL_VOID(glDrawArrays, (GLenum mode, GLint first, GLsizei count), (mode, first, count), 3, "GLenum", mode, "GLint", first, "GLsizei", count)
+TRACE_GL_VOID(glDrawElements, (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices), (mode, count, type, indices), 4, "GLenum", mode, "GLsizei", count, "GLenum", type, "const GLvoid *", indices)
+TRACE_GL_VOID(glDrawTexfOES, (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height), (x, y, z, width, height), 5, "GLfloat", x, "GLfloat", y, "GLfloat", z, "GLfloat", width, "GLfloat", height)
+TRACE_GL_VOID(glDrawTexfvOES, (const GLfloat *coords), (coords), 1, "const GLfloat *", coords)
+TRACE_GL_VOID(glDrawTexiOES, (GLint x, GLint y, GLint z, GLint width, GLint height), (x, y, z, width, height), 5, "GLint", x, "GLint", y, "GLint", z, "GLint", width, "GLint", height)
+TRACE_GL_VOID(glDrawTexivOES, (const GLint *coords), (coords), 1, "const GLint *", coords)
+TRACE_GL_VOID(glDrawTexsOES, (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height), (x, y, z, width, height), 5, "GLshort", x, "GLshort", y, "GLshort", z, "GLshort", width, "GLshort", height)
+TRACE_GL_VOID(glDrawTexsvOES, (const GLshort *coords), (coords), 1, "const GLshort *", coords)
+TRACE_GL_VOID(glDrawTexxOES, (GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height), (x, y, z, width, height), 5, "GLfixed", x, "GLfixed", y, "GLfixed", z, "GLfixed", width, "GLfixed", height)
+TRACE_GL_VOID(glDrawTexxvOES, (const GLfixed *coords), (coords), 1, "const GLfixed *", coords)
+TRACE_GL_VOID(glEGLImageTargetRenderbufferStorageOES, (GLenum target, GLeglImageOES image), (target, image), 2, "GLenum", target, "GLeglImageOES", image)
+TRACE_GL_VOID(glEGLImageTargetTexture2DOES, (GLenum target, GLeglImageOES image), (target, image), 2, "GLenum", target, "GLeglImageOES", image)
+TRACE_GL_VOID(glEnable, (GLenum cap), (cap), 1, "GLenum", cap)
+TRACE_GL_VOID(glEnableClientState, (GLenum array), (array), 1, "GLenum", array)
+TRACE_GL_VOID(glEnableDriverControlQCOM, (GLuint driverControl), (driverControl), 1, "GLuint", driverControl)
+TRACE_GL_VOID(glEnableVertexAttribArray, (GLuint index), (index), 1, "GLuint", index)
+TRACE_GL_VOID(glEndPerfMonitorAMD, (GLuint monitor), (monitor), 1, "GLuint", monitor)
+TRACE_GL_VOID(glEndTilingQCOM, (GLbitfield preserveMask), (preserveMask), 1, "GLbitfield", preserveMask)
+TRACE_GL_VOID(glExtGetBufferPointervQCOM, (GLenum target, GLvoid **params), (target, params), 2, "GLenum", target, "GLvoid **", params)
+TRACE_GL_VOID(glExtGetBuffersQCOM, (GLuint *buffers, GLint maxBuffers, GLint *numBuffers), (buffers, maxBuffers, numBuffers), 3, "GLuint *", buffers, "GLint", maxBuffers, "GLint *", numBuffers)
+TRACE_GL_VOID(glExtGetFramebuffersQCOM, (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers), (framebuffers, maxFramebuffers, numFramebuffers), 3, "GLuint *", framebuffers, "GLint", maxFramebuffers, "GLint *", numFramebuffers)
+TRACE_GL_VOID(glExtGetProgramBinarySourceQCOM, (GLuint program, GLenum shadertype, GLchar *source, GLint *length), (program, shadertype, source, length), 4, "GLuint", program, "GLenum", shadertype, "GLchar *", source, "GLint *", length)
+TRACE_GL_VOID(glExtGetProgramsQCOM, (GLuint *programs, GLint maxPrograms, GLint *numPrograms), (programs, maxPrograms, numPrograms), 3, "GLuint *", programs, "GLint", maxPrograms, "GLint *", numPrograms)
+TRACE_GL_VOID(glExtGetRenderbuffersQCOM, (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers), (renderbuffers, maxRenderbuffers, numRenderbuffers), 3, "GLuint *", renderbuffers, "GLint", maxRenderbuffers, "GLint *", numRenderbuffers)
+TRACE_GL_VOID(glExtGetShadersQCOM, (GLuint *shaders, GLint maxShaders, GLint *numShaders), (shaders, maxShaders, numShaders), 3, "GLuint *", shaders, "GLint", maxShaders, "GLint *", numShaders)
+TRACE_GL_VOID(glExtGetTexLevelParameterivQCOM, (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params), (texture, face, level, pname, params), 5, "GLuint", texture, "GLenum", face, "GLint", level, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glExtGetTexSubImageQCOM, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLenum", type, "GLvoid *", texels)
+TRACE_GL_VOID(glExtGetTexturesQCOM, (GLuint *textures, GLint maxTextures, GLint *numTextures), (textures, maxTextures, numTextures), 3, "GLuint *", textures, "GLint", maxTextures, "GLint *", numTextures)
+TRACE_GL(GLboolean, glExtIsProgramBinaryQCOM, (GLuint program), (program), 1, "GLuint", program)
+TRACE_GL_VOID(glExtTexObjectStateOverrideiQCOM, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glFinish, (void), (), 0)
+TRACE_GL_VOID(glFinishFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
+TRACE_GL_VOID(glFlush, (void), (), 0)
+TRACE_GL_VOID(glFogf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glFogfv, (GLenum pname, const GLfloat *params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glFogx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glFogxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glFogxv, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glFogxvOES, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glFramebufferRenderbuffer, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer), (target, attachment, renderbuffertarget, renderbuffer), 4, "GLenum", target, "GLenum", attachment, "GLenum", renderbuffertarget, "GLuint", renderbuffer)
+TRACE_GL_VOID(glFramebufferRenderbufferOES, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer), (target, attachment, renderbuffertarget, renderbuffer), 4, "GLenum", target, "GLenum", attachment, "GLenum", renderbuffertarget, "GLuint", renderbuffer)
+TRACE_GL_VOID(glFramebufferTexture2D, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level), (target, attachment, textarget, texture, level), 5, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level)
+TRACE_GL_VOID(glFramebufferTexture2DMultisampleIMG, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples), (target, attachment, textarget, texture, level, samples), 6, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level, "GLsizei", samples)
+TRACE_GL_VOID(glFramebufferTexture2DOES, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level), (target, attachment, textarget, texture, level), 5, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level)
+TRACE_GL_VOID(glFramebufferTexture3DOES, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset), (target, attachment, textarget, texture, level, zoffset), 6, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level, "GLint", zoffset)
+TRACE_GL_VOID(glFrontFace, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glFrustumf, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glFrustumfOES, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glFrustumx, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glFrustumxOES, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glGenBuffers, (GLsizei n, GLuint *buffers), (n, buffers), 2, "GLsizei", n, "GLuint *", buffers)
+TRACE_GL_VOID(glGenFencesNV, (GLsizei n, GLuint *fences), (n, fences), 2, "GLsizei", n, "GLuint *", fences)
+TRACE_GL_VOID(glGenFramebuffers, (GLsizei n, GLuint* framebuffers), (n, framebuffers), 2, "GLsizei", n, "GLuint*", framebuffers)
+TRACE_GL_VOID(glGenFramebuffersOES, (GLsizei n, GLuint* framebuffers), (n, framebuffers), 2, "GLsizei", n, "GLuint*", framebuffers)
+TRACE_GL_VOID(glGenPerfMonitorsAMD, (GLsizei n, GLuint *monitors), (n, monitors), 2, "GLsizei", n, "GLuint *", monitors)
+TRACE_GL_VOID(glGenRenderbuffers, (GLsizei n, GLuint* renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "GLuint*", renderbuffers)
+TRACE_GL_VOID(glGenRenderbuffersOES, (GLsizei n, GLuint* renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "GLuint*", renderbuffers)
+TRACE_GL_VOID(glGenTextures, (GLsizei n, GLuint *textures), (n, textures), 2, "GLsizei", n, "GLuint *", textures)
+TRACE_GL_VOID(glGenVertexArraysOES, (GLsizei n, GLuint *arrays), (n, arrays), 2, "GLsizei", n, "GLuint *", arrays)
+TRACE_GL_VOID(glGenerateMipmap, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL_VOID(glGenerateMipmapOES, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL_VOID(glGetActiveAttrib, (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name), (program, index, bufsize, length, size, type, name), 7, "GLuint", program, "GLuint", index, "GLsizei", bufsize, "GLsizei*", length, "GLint*", size, "GLenum*", type, "GLchar*", name)
+TRACE_GL_VOID(glGetActiveUniform, (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name), (program, index, bufsize, length, size, type, name), 7, "GLuint", program, "GLuint", index, "GLsizei", bufsize, "GLsizei*", length, "GLint*", size, "GLenum*", type, "GLchar*", name)
+TRACE_GL_VOID(glGetAttachedShaders, (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders), (program, maxcount, count, shaders), 4, "GLuint", program, "GLsizei", maxcount, "GLsizei*", count, "GLuint*", shaders)
+TRACE_GL(int, glGetAttribLocation, (GLuint program, const GLchar* name), (program, name), 2, "GLuint", program, "const GLchar*", name)
+TRACE_GL_VOID(glGetBooleanv, (GLenum pname, GLboolean *params), (pname, params), 2, "GLenum", pname, "GLboolean *", params)
+TRACE_GL_VOID(glGetBufferParameteriv, (GLenum target, GLenum pname, GLint *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetBufferPointervOES, (GLenum target, GLenum pname, GLvoid ** params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLvoid **", params)
+TRACE_GL_VOID(glGetClipPlanef, (GLenum pname, GLfloat eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfloat", eqn)
+TRACE_GL_VOID(glGetClipPlanefOES, (GLenum pname, GLfloat eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfloat", eqn)
+TRACE_GL_VOID(glGetClipPlanex, (GLenum pname, GLfixed eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfixed", eqn)
+TRACE_GL_VOID(glGetClipPlanexOES, (GLenum pname, GLfixed eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfixed", eqn)
+TRACE_GL_VOID(glGetDriverControlStringQCOM, (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString), (driverControl, bufSize, length, driverControlString), 4, "GLuint", driverControl, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", driverControlString)
+TRACE_GL_VOID(glGetDriverControlsQCOM, (GLint *num, GLsizei size, GLuint *driverControls), (num, size, driverControls), 3, "GLint *", num, "GLsizei", size, "GLuint *", driverControls)
+TRACE_GL(GLenum, glGetError, (void), (), 0)
+TRACE_GL_VOID(glGetFenceivNV, (GLuint fence, GLenum pname, GLint *params), (fence, pname, params), 3, "GLuint", fence, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetFixedv, (GLenum pname, GLfixed *params), (pname, params), 2, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetFixedvOES, (GLenum pname, GLfixed *params), (pname, params), 2, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetFloatv, (GLenum pname, GLfloat *params), (pname, params), 2, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetFramebufferAttachmentParameteriv, (GLenum target, GLenum attachment, GLenum pname, GLint* params), (target, attachment, pname, params), 4, "GLenum", target, "GLenum", attachment, "GLenum", pname, "GLint*", params)
+TRACE_GL_VOID(glGetFramebufferAttachmentParameterivOES, (GLenum target, GLenum attachment, GLenum pname, GLint* params), (target, attachment, pname, params), 4, "GLenum", target, "GLenum", attachment, "GLenum", pname, "GLint*", params)
+TRACE_GL_VOID(glGetIntegerv, (GLenum pname, GLint *params), (pname, params), 2, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetLightfv, (GLenum light, GLenum pname, GLfloat *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetLightxv, (GLenum light, GLenum pname, GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetLightxvOES, (GLenum light, GLenum pname, GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetMaterialfv, (GLenum face, GLenum pname, GLfloat *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetMaterialxv, (GLenum face, GLenum pname, GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetMaterialxvOES, (GLenum face, GLenum pname, GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetPerfMonitorCounterDataAMD, (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten), (monitor, pname, dataSize, data, bytesWritten), 5, "GLuint", monitor, "GLenum", pname, "GLsizei", dataSize, "GLuint *", data, "GLint *", bytesWritten)
+TRACE_GL_VOID(glGetPerfMonitorCounterInfoAMD, (GLuint group, GLuint counter, GLenum pname, GLvoid *data), (group, counter, pname, data), 4, "GLuint", group, "GLuint", counter, "GLenum", pname, "GLvoid *", data)
+TRACE_GL_VOID(glGetPerfMonitorCounterStringAMD, (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString), (group, counter, bufSize, length, counterString), 5, "GLuint", group, "GLuint", counter, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", counterString)
+TRACE_GL_VOID(glGetPerfMonitorCountersAMD, (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters), (group, numCounters, maxActiveCounters, counterSize, counters), 5, "GLuint", group, "GLint *", numCounters, "GLint *", maxActiveCounters, "GLsizei", counterSize, "GLuint *", counters)
+TRACE_GL_VOID(glGetPerfMonitorGroupStringAMD, (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString), (group, bufSize, length, groupString), 4, "GLuint", group, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", groupString)
+TRACE_GL_VOID(glGetPerfMonitorGroupsAMD, (GLint *numGroups, GLsizei groupsSize, GLuint *groups), (numGroups, groupsSize, groups), 3, "GLint *", numGroups, "GLsizei", groupsSize, "GLuint *", groups)
+TRACE_GL_VOID(glGetPointerv, (GLenum pname, GLvoid **params), (pname, params), 2, "GLenum", pname, "GLvoid **", params)
+TRACE_GL_VOID(glGetProgramBinaryOES, (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary), (program, bufSize, length, binaryFormat, binary), 5, "GLuint", program, "GLsizei", bufSize, "GLsizei *", length, "GLenum *", binaryFormat, "GLvoid *", binary)
+TRACE_GL_VOID(glGetProgramInfoLog, (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog), (program, bufsize, length, infolog), 4, "GLuint", program, "GLsizei", bufsize, "GLsizei*", length, "GLchar*", infolog)
+TRACE_GL_VOID(glGetProgramiv, (GLuint program, GLenum pname, GLint* params), (program, pname, params), 3, "GLuint", program, "GLenum", pname, "GLint*", params)
+TRACE_GL_VOID(glGetRenderbufferParameteriv, (GLenum target, GLenum pname, GLint* params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint*", params)
+TRACE_GL_VOID(glGetRenderbufferParameterivOES, (GLenum target, GLenum pname, GLint* params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint*", params)
+TRACE_GL_VOID(glGetShaderInfoLog, (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog), (shader, bufsize, length, infolog), 4, "GLuint", shader, "GLsizei", bufsize, "GLsizei*", length, "GLchar*", infolog)
+TRACE_GL_VOID(glGetShaderPrecisionFormat, (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision), (shadertype, precisiontype, range, precision), 4, "GLenum", shadertype, "GLenum", precisiontype, "GLint*", range, "GLint*", precision)
+TRACE_GL_VOID(glGetShaderSource, (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source), (shader, bufsize, length, source), 4, "GLuint", shader, "GLsizei", bufsize, "GLsizei*", length, "GLchar*", source)
+TRACE_GL_VOID(glGetShaderiv, (GLuint shader, GLenum pname, GLint* params), (shader, pname, params), 3, "GLuint", shader, "GLenum", pname, "GLint*", params)
+TRACE_GL(const GLubyte *, glGetString, (GLenum name), (name), 1, "GLenum", name)
+TRACE_GL_VOID(glGetTexEnvfv, (GLenum env, GLenum pname, GLfloat *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetTexEnviv, (GLenum env, GLenum pname, GLint *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetTexEnvxv, (GLenum env, GLenum pname, GLfixed *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexEnvxvOES, (GLenum env, GLenum pname, GLfixed *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexGenfvOES, (GLenum coord, GLenum pname, GLfloat *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetTexGenivOES, (GLenum coord, GLenum pname, GLint *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetTexGenxvOES, (GLenum coord, GLenum pname, GLfixed *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexParameterfv, (GLenum target, GLenum pname, GLfloat *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetTexParameteriv, (GLenum target, GLenum pname, GLint *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetTexParameterxv, (GLenum target, GLenum pname, GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexParameterxvOES, (GLenum target, GLenum pname, GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfixed *", params)
+TRACE_GL(int, glGetUniformLocation, (GLuint program, const GLchar* name), (program, name), 2, "GLuint", program, "const GLchar*", name)
+TRACE_GL_VOID(glGetUniformfv, (GLuint program, GLint location, GLfloat* params), (program, location, params), 3, "GLuint", program, "GLint", location, "GLfloat*", params)
+TRACE_GL_VOID(glGetUniformiv, (GLuint program, GLint location, GLint* params), (program, location, params), 3, "GLuint", program, "GLint", location, "GLint*", params)
+TRACE_GL_VOID(glGetVertexAttribPointerv, (GLuint index, GLenum pname, GLvoid** pointer), (index, pname, pointer), 3, "GLuint", index, "GLenum", pname, "GLvoid**", pointer)
+TRACE_GL_VOID(glGetVertexAttribfv, (GLuint index, GLenum pname, GLfloat* params), (index, pname, params), 3, "GLuint", index, "GLenum", pname, "GLfloat*", params)
+TRACE_GL_VOID(glGetVertexAttribiv, (GLuint index, GLenum pname, GLint* params), (index, pname, params), 3, "GLuint", index, "GLenum", pname, "GLint*", params)
+TRACE_GL_VOID(glHint, (GLenum target, GLenum mode), (target, mode), 2, "GLenum", target, "GLenum", mode)
+TRACE_GL(GLboolean, glIsBuffer, (GLuint buffer), (buffer), 1, "GLuint", buffer)
+TRACE_GL(GLboolean, glIsEnabled, (GLenum cap), (cap), 1, "GLenum", cap)
+TRACE_GL(GLboolean, glIsFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
+TRACE_GL(GLboolean, glIsFramebuffer, (GLuint framebuffer), (framebuffer), 1, "GLuint", framebuffer)
+TRACE_GL(GLboolean, glIsFramebufferOES, (GLuint framebuffer), (framebuffer), 1, "GLuint", framebuffer)
+TRACE_GL(GLboolean, glIsProgram, (GLuint program), (program), 1, "GLuint", program)
+TRACE_GL(GLboolean, glIsRenderbuffer, (GLuint renderbuffer), (renderbuffer), 1, "GLuint", renderbuffer)
+TRACE_GL(GLboolean, glIsRenderbufferOES, (GLuint renderbuffer), (renderbuffer), 1, "GLuint", renderbuffer)
+TRACE_GL(GLboolean, glIsShader, (GLuint shader), (shader), 1, "GLuint", shader)
+TRACE_GL(GLboolean, glIsTexture, (GLuint texture), (texture), 1, "GLuint", texture)
+TRACE_GL(GLboolean, glIsVertexArrayOES, (GLuint array), (array), 1, "GLuint", array)
+TRACE_GL_VOID(glLightModelf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glLightModelfv, (GLenum pname, const GLfloat *params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glLightModelx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightModelxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightModelxv, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLightModelxvOES, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLightf, (GLenum light, GLenum pname, GLfloat param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glLightfv, (GLenum light, GLenum pname, const GLfloat *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glLightx, (GLenum light, GLenum pname, GLfixed param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightxOES, (GLenum light, GLenum pname, GLfixed param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightxv, (GLenum light, GLenum pname, const GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLightxvOES, (GLenum light, GLenum pname, const GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLineWidth, (GLfloat width), (width), 1, "GLfloat", width)
+TRACE_GL_VOID(glLineWidthx, (GLfixed width), (width), 1, "GLfixed", width)
+TRACE_GL_VOID(glLineWidthxOES, (GLfixed width), (width), 1, "GLfixed", width)
+TRACE_GL_VOID(glLinkProgram, (GLuint program), (program), 1, "GLuint", program)
+TRACE_GL_VOID(glLoadIdentity, (void), (), 0)
+TRACE_GL_VOID(glLoadMatrixf, (const GLfloat *m), (m), 1, "const GLfloat *", m)
+TRACE_GL_VOID(glLoadMatrixx, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glLoadMatrixxOES, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glLoadPaletteFromModelViewMatrixOES, (void), (), 0)
+TRACE_GL_VOID(glLogicOp, (GLenum opcode), (opcode), 1, "GLenum", opcode)
+TRACE_GL(void*, glMapBufferOES, (GLenum target, GLenum access), (target, access), 2, "GLenum", target, "GLenum", access)
+TRACE_GL_VOID(glMaterialf, (GLenum face, GLenum pname, GLfloat param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glMaterialfv, (GLenum face, GLenum pname, const GLfloat *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glMaterialx, (GLenum face, GLenum pname, GLfixed param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glMaterialxOES, (GLenum face, GLenum pname, GLfixed param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glMaterialxv, (GLenum face, GLenum pname, const GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glMaterialxvOES, (GLenum face, GLenum pname, const GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glMatrixIndexPointerOES, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glMatrixMode, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glMultMatrixf, (const GLfloat *m), (m), 1, "const GLfloat *", m)
+TRACE_GL_VOID(glMultMatrixx, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glMultMatrixxOES, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glMultiDrawArraysEXT, (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount), (mode, first, count, primcount), 4, "GLenum", mode, "GLint *", first, "GLsizei *", count, "GLsizei", primcount)
+TRACE_GL_VOID(glMultiDrawElementsEXT, (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount), (mode, count, type, indices, primcount), 5, "GLenum", mode, "const GLsizei *", count, "GLenum", type, "const GLvoid* *", indices, "GLsizei", primcount)
+TRACE_GL_VOID(glMultiTexCoord4f, (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q), (target, s, t, r, q), 5, "GLenum", target, "GLfloat", s, "GLfloat", t, "GLfloat", r, "GLfloat", q)
+TRACE_GL_VOID(glMultiTexCoord4x, (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q), (target, s, t, r, q), 5, "GLenum", target, "GLfixed", s, "GLfixed", t, "GLfixed", r, "GLfixed", q)
+TRACE_GL_VOID(glMultiTexCoord4xOES, (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q), (target, s, t, r, q), 5, "GLenum", target, "GLfixed", s, "GLfixed", t, "GLfixed", r, "GLfixed", q)
+TRACE_GL_VOID(glNormal3f, (GLfloat nx, GLfloat ny, GLfloat nz), (nx, ny, nz), 3, "GLfloat", nx, "GLfloat", ny, "GLfloat", nz)
+TRACE_GL_VOID(glNormal3x, (GLfixed nx, GLfixed ny, GLfixed nz), (nx, ny, nz), 3, "GLfixed", nx, "GLfixed", ny, "GLfixed", nz)
+TRACE_GL_VOID(glNormal3xOES, (GLfixed nx, GLfixed ny, GLfixed nz), (nx, ny, nz), 3, "GLfixed", nx, "GLfixed", ny, "GLfixed", nz)
+TRACE_GL_VOID(glNormalPointer, (GLenum type, GLsizei stride, const GLvoid *pointer), (type, stride, pointer), 3, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glOrthof, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glOrthofOES, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glOrthox, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glOrthoxOES, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glPixelStorei, (GLenum pname, GLint param), (pname, param), 2, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glPointParameterf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glPointParameterfv, (GLenum pname, const GLfloat *params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glPointParameterx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glPointParameterxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glPointParameterxv, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glPointParameterxvOES, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glPointSize, (GLfloat size), (size), 1, "GLfloat", size)
+TRACE_GL_VOID(glPointSizePointerOES, (GLenum type, GLsizei stride, const GLvoid *pointer), (type, stride, pointer), 3, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glPointSizex, (GLfixed size), (size), 1, "GLfixed", size)
+TRACE_GL_VOID(glPointSizexOES, (GLfixed size), (size), 1, "GLfixed", size)
+TRACE_GL_VOID(glPolygonOffset, (GLfloat factor, GLfloat units), (factor, units), 2, "GLfloat", factor, "GLfloat", units)
+TRACE_GL_VOID(glPolygonOffsetx, (GLfixed factor, GLfixed units), (factor, units), 2, "GLfixed", factor, "GLfixed", units)
+TRACE_GL_VOID(glPolygonOffsetxOES, (GLfixed factor, GLfixed units), (factor, units), 2, "GLfixed", factor, "GLfixed", units)
+TRACE_GL_VOID(glPopMatrix, (void), (), 0)
+TRACE_GL_VOID(glProgramBinaryOES, (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length), (program, binaryFormat, binary, length), 4, "GLuint", program, "GLenum", binaryFormat, "const GLvoid *", binary, "GLint", length)
+TRACE_GL_VOID(glPushMatrix, (void), (), 0)
+TRACE_GL(GLbitfield, glQueryMatrixxOES, (GLfixed mantissa[16], GLint exponent[16]), (mantissa, exponent), 2, "GLfixed", mantissa, "GLint", exponent)
+TRACE_GL_VOID(glReadPixels, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels), (x, y, width, height, format, type, pixels), 7, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height, "GLenum", format, "GLenum", type, "GLvoid *", pixels)
+TRACE_GL_VOID(glReleaseShaderCompiler, (void), (), 0)
+TRACE_GL_VOID(glRenderbufferStorage, (GLenum target, GLenum internalformat, GLsizei width, GLsizei height), (target, internalformat, width, height), 4, "GLenum", target, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glRenderbufferStorageMultisampleIMG, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height), (target, samples, internalformat, width, height), 5, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glRenderbufferStorageOES, (GLenum target, GLenum internalformat, GLsizei width, GLsizei height), (target, internalformat, width, height), 4, "GLenum", target, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glRotatef, (GLfloat angle, GLfloat x, GLfloat y, GLfloat z), (angle, x, y, z), 4, "GLfloat", angle, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glRotatex, (GLfixed angle, GLfixed x, GLfixed y, GLfixed z), (angle, x, y, z), 4, "GLfixed", angle, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glRotatexOES, (GLfixed angle, GLfixed x, GLfixed y, GLfixed z), (angle, x, y, z), 4, "GLfixed", angle, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glSampleCoverage, (GLclampf value, GLboolean invert), (value, invert), 2, "GLclampf", value, "GLboolean", invert)
+TRACE_GL_VOID(glSampleCoveragex, (GLclampx value, GLboolean invert), (value, invert), 2, "GLclampx", value, "GLboolean", invert)
+TRACE_GL_VOID(glSampleCoveragexOES, (GLclampx value, GLboolean invert), (value, invert), 2, "GLclampx", value, "GLboolean", invert)
+TRACE_GL_VOID(glScalef, (GLfloat x, GLfloat y, GLfloat z), (x, y, z), 3, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glScalex, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glScalexOES, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glScissor, (GLint x, GLint y, GLsizei width, GLsizei height), (x, y, width, height), 4, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glSelectPerfMonitorCountersAMD, (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList), (monitor, enable, group, numCounters, countersList), 5, "GLuint", monitor, "GLboolean", enable, "GLuint", group, "GLint", numCounters, "GLuint *", countersList)
+TRACE_GL_VOID(glSetFenceNV, (GLuint fence, GLenum condition), (fence, condition), 2, "GLuint", fence, "GLenum", condition)
+TRACE_GL_VOID(glShadeModel, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glShaderBinary, (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length), (n, shaders, binaryformat, binary, length), 5, "GLsizei", n, "const GLuint*", shaders, "GLenum", binaryformat, "const GLvoid*", binary, "GLsizei", length)
+TRACE_GL_VOID(glShaderSource, (GLuint shader, GLsizei count, const GLchar** string, const GLint* length), (shader, count, string, length), 4, "GLuint", shader, "GLsizei", count, "const GLchar**", string, "const GLint*", length)
+TRACE_GL_VOID(glStartTilingQCOM, (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask), (x, y, width, height, preserveMask), 5, "GLuint", x, "GLuint", y, "GLuint", width, "GLuint", height, "GLbitfield", preserveMask)
+TRACE_GL_VOID(glStencilFunc, (GLenum func, GLint ref, GLuint mask), (func, ref, mask), 3, "GLenum", func, "GLint", ref, "GLuint", mask)
+TRACE_GL_VOID(glStencilFuncSeparate, (GLenum face, GLenum func, GLint ref, GLuint mask), (face, func, ref, mask), 4, "GLenum", face, "GLenum", func, "GLint", ref, "GLuint", mask)
+TRACE_GL_VOID(glStencilMask, (GLuint mask), (mask), 1, "GLuint", mask)
+TRACE_GL_VOID(glStencilMaskSeparate, (GLenum face, GLuint mask), (face, mask), 2, "GLenum", face, "GLuint", mask)
+TRACE_GL_VOID(glStencilOp, (GLenum fail, GLenum zfail, GLenum zpass), (fail, zfail, zpass), 3, "GLenum", fail, "GLenum", zfail, "GLenum", zpass)
+TRACE_GL_VOID(glStencilOpSeparate, (GLenum face, GLenum fail, GLenum zfail, GLenum zpass), (face, fail, zfail, zpass), 4, "GLenum", face, "GLenum", fail, "GLenum", zfail, "GLenum", zpass)
+TRACE_GL(GLboolean, glTestFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
+TRACE_GL_VOID(glTexCoordPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glTexEnvf, (GLenum target, GLenum pname, GLfloat param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glTexEnvfv, (GLenum target, GLenum pname, const GLfloat *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glTexEnvi, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glTexEnviv, (GLenum target, GLenum pname, const GLint *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLint *", params)
+TRACE_GL_VOID(glTexEnvx, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexEnvxOES, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexEnvxv, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexEnvxvOES, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexGenfOES, (GLenum coord, GLenum pname, GLfloat param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glTexGenfvOES, (GLenum coord, GLenum pname, const GLfloat *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glTexGeniOES, (GLenum coord, GLenum pname, GLint param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glTexGenivOES, (GLenum coord, GLenum pname, const GLint *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLint *", params)
+TRACE_GL_VOID(glTexGenxOES, (GLenum coord, GLenum pname, GLfixed param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexGenxvOES, (GLenum coord, GLenum pname, const GLfixed *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexImage2D, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels), (target, level, internalformat, width, height, border, format, type, pixels), 9, "GLenum", target, "GLint", level, "GLint", internalformat, "GLsizei", width, "GLsizei", height, "GLint", border, "GLenum", format, "GLenum", type, "const GLvoid *", pixels)
+TRACE_GL_VOID(glTexImage3DOES, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels), (target, level, internalformat, width, height, depth, border, format, type, pixels), 10, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLint", border, "GLenum", format, "GLenum", type, "const GLvoid*", pixels)
+TRACE_GL_VOID(glTexParameterf, (GLenum target, GLenum pname, GLfloat param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glTexParameterfv, (GLenum target, GLenum pname, const GLfloat *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glTexParameteri, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glTexParameteriv, (GLenum target, GLenum pname, const GLint *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLint *", params)
+TRACE_GL_VOID(glTexParameterx, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexParameterxOES, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexParameterxv, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexParameterxvOES, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels), (target, level, xoffset, yoffset, width, height, format, type, pixels), 9, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLsizei", width, "GLsizei", height, "GLenum", format, "GLenum", type, "const GLvoid *", pixels)
+TRACE_GL_VOID(glTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLenum", type, "const GLvoid*", pixels)
+TRACE_GL_VOID(glTranslatef, (GLfloat x, GLfloat y, GLfloat z), (x, y, z), 3, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glTranslatex, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glTranslatexOES, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glUniform1f, (GLint location, GLfloat x), (location, x), 2, "GLint", location, "GLfloat", x)
+TRACE_GL_VOID(glUniform1fv, (GLint location, GLsizei count, const GLfloat* v), (location, count, v), 3, "GLint", location, "GLsizei", count, "const GLfloat*", v)
+TRACE_GL_VOID(glUniform1i, (GLint location, GLint x), (location, x), 2, "GLint", location, "GLint", x)
+TRACE_GL_VOID(glUniform1iv, (GLint location, GLsizei count, const GLint* v), (location, count, v), 3, "GLint", location, "GLsizei", count, "const GLint*", v)
+TRACE_GL_VOID(glUniform2f, (GLint location, GLfloat x, GLfloat y), (location, x, y), 3, "GLint", location, "GLfloat", x, "GLfloat", y)
+TRACE_GL_VOID(glUniform2fv, (GLint location, GLsizei count, const GLfloat* v), (location, count, v), 3, "GLint", location, "GLsizei", count, "const GLfloat*", v)
+TRACE_GL_VOID(glUniform2i, (GLint location, GLint x, GLint y), (location, x, y), 3, "GLint", location, "GLint", x, "GLint", y)
+TRACE_GL_VOID(glUniform2iv, (GLint location, GLsizei count, const GLint* v), (location, count, v), 3, "GLint", location, "GLsizei", count, "const GLint*", v)
+TRACE_GL_VOID(glUniform3f, (GLint location, GLfloat x, GLfloat y, GLfloat z), (location, x, y, z), 4, "GLint", location, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glUniform3fv, (GLint location, GLsizei count, const GLfloat* v), (location, count, v), 3, "GLint", location, "GLsizei", count, "const GLfloat*", v)
+TRACE_GL_VOID(glUniform3i, (GLint location, GLint x, GLint y, GLint z), (location, x, y, z), 4, "GLint", location, "GLint", x, "GLint", y, "GLint", z)
+TRACE_GL_VOID(glUniform3iv, (GLint location, GLsizei count, const GLint* v), (location, count, v), 3, "GLint", location, "GLsizei", count, "const GLint*", v)
+TRACE_GL_VOID(glUniform4f, (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w), (location, x, y, z, w), 5, "GLint", location, "GLfloat", x, "GLfloat", y, "GLfloat", z, "GLfloat", w)
+TRACE_GL_VOID(glUniform4fv, (GLint location, GLsizei count, const GLfloat* v), (location, count, v), 3, "GLint", location, "GLsizei", count, "const GLfloat*", v)
+TRACE_GL_VOID(glUniform4i, (GLint location, GLint x, GLint y, GLint z, GLint w), (location, x, y, z, w), 5, "GLint", location, "GLint", x, "GLint", y, "GLint", z, "GLint", w)
+TRACE_GL_VOID(glUniform4iv, (GLint location, GLsizei count, const GLint* v), (location, count, v), 3, "GLint", location, "GLsizei", count, "const GLint*", v)
+TRACE_GL_VOID(glUniformMatrix2fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat*", value)
+TRACE_GL_VOID(glUniformMatrix3fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat*", value)
+TRACE_GL_VOID(glUniformMatrix4fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat*", value)
+TRACE_GL(GLboolean, glUnmapBufferOES, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL_VOID(glUseProgram, (GLuint program), (program), 1, "GLuint", program)
+TRACE_GL_VOID(glValidateProgram, (GLuint program), (program), 1, "GLuint", program)
+TRACE_GL_VOID(glVertexAttrib1f, (GLuint indx, GLfloat x), (indx, x), 2, "GLuint", indx, "GLfloat", x)
+TRACE_GL_VOID(glVertexAttrib1fv, (GLuint indx, const GLfloat* values), (indx, values), 2, "GLuint", indx, "const GLfloat*", values)
+TRACE_GL_VOID(glVertexAttrib2f, (GLuint indx, GLfloat x, GLfloat y), (indx, x, y), 3, "GLuint", indx, "GLfloat", x, "GLfloat", y)
+TRACE_GL_VOID(glVertexAttrib2fv, (GLuint indx, const GLfloat* values), (indx, values), 2, "GLuint", indx, "const GLfloat*", values)
+TRACE_GL_VOID(glVertexAttrib3f, (GLuint indx, GLfloat x, GLfloat y, GLfloat z), (indx, x, y, z), 4, "GLuint", indx, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glVertexAttrib3fv, (GLuint indx, const GLfloat* values), (indx, values), 2, "GLuint", indx, "const GLfloat*", values)
+TRACE_GL_VOID(glVertexAttrib4f, (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w), (indx, x, y, z, w), 5, "GLuint", indx, "GLfloat", x, "GLfloat", y, "GLfloat", z, "GLfloat", w)
+TRACE_GL_VOID(glVertexAttrib4fv, (GLuint indx, const GLfloat* values), (indx, values), 2, "GLuint", indx, "const GLfloat*", values)
+TRACE_GL_VOID(glVertexAttribPointer, (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr), (indx, size, type, normalized, stride, ptr), 6, "GLuint", indx, "GLint", size, "GLenum", type, "GLboolean", normalized, "GLsizei", stride, "const GLvoid*", ptr)
+TRACE_GL_VOID(glVertexPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glViewport, (GLint x, GLint y, GLsizei width, GLsizei height), (x, y, width, height), 4, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glWeightPointerOES, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
diff --git a/opengl/tests/gl2_yuvtex/Android.mk b/opengl/tests/gl2_yuvtex/Android.mk
new file mode 100644
index 0000000..6304700
--- /dev/null
+++ b/opengl/tests/gl2_yuvtex/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	gl2_yuvtex.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv2 \
+    libui
+
+LOCAL_MODULE:= test-opengl-gl2_yuvtex
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp b/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
new file mode 100644
index 0000000..602ea1a
--- /dev/null
+++ b/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sched.h>
+#include <sys/resource.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <utils/Timers.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+static void printGLString(const char *name, GLenum s) {
+    // fprintf(stderr, "printGLString %s, %d\n", name, s);
+    const char *v = (const char *) glGetString(s);
+    // int error = glGetError();
+    // fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error,
+    //        (unsigned int) v);
+    // if ((v < (const char*) 0) || (v > (const char*) 0x10000))
+    //    fprintf(stderr, "GL %s = %s\n", name, v);
+    // else
+    //    fprintf(stderr, "GL %s = (null) 0x%08x\n", name, (unsigned int) v);
+    fprintf(stderr, "GL %s = %s\n", name, v);
+}
+
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+    if (returnVal != EGL_TRUE) {
+        fprintf(stderr, "%s() returned %d\n", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+            = eglGetError()) {
+        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
+                error);
+    }
+}
+
+static void checkGlError(const char* op) {
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
+    }
+}
+
+static const char gVertexShader[] = "attribute vec4 vPosition;\n"
+    "varying vec2 yuvTexCoords;\n"
+    "void main() {\n"
+    "  yuvTexCoords = vPosition.xy + vec2(0.5, 0.5);\n"
+    "  gl_Position = vPosition;\n"
+    "}\n";
+
+static const char gFragmentShader[] = "#extension GL_OES_EGL_image_external : require\n"
+    "precision mediump float;\n"
+    "uniform samplerExternalOES yuvTexSampler;\n"
+    "varying vec2 yuvTexCoords;\n"
+    "void main() {\n"
+    "  gl_FragColor = texture2D(yuvTexSampler, yuvTexCoords);\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);
+                    fprintf(stderr, "Could not compile shader %d:\n%s\n",
+                            shaderType, buf);
+                    free(buf);
+                }
+            } else {
+                fprintf(stderr, "Guessing at GL_INFO_LOG_LENGTH size\n");
+                char* buf = (char*) malloc(0x1000);
+                if (buf) {
+                    glGetShaderInfoLog(shader, 0x1000, NULL, buf);
+                    fprintf(stderr, "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);
+                    fprintf(stderr, "Could not link program:\n%s\n", buf);
+                    free(buf);
+                }
+            }
+            glDeleteProgram(program);
+            program = 0;
+        }
+    }
+    return program;
+}
+
+GLuint gProgram;
+GLint gvPositionHandle;
+GLint gYuvTexSamplerHandle;
+
+bool setupGraphics(int w, int h) {
+    gProgram = createProgram(gVertexShader, gFragmentShader);
+    if (!gProgram) {
+        return false;
+    }
+    gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
+    checkGlError("glGetAttribLocation");
+    fprintf(stderr, "glGetAttribLocation(\"vPosition\") = %d\n",
+            gvPositionHandle);
+    gYuvTexSamplerHandle = glGetUniformLocation(gProgram, "yuvTexSampler");
+    checkGlError("glGetUniformLocation");
+    fprintf(stderr, "glGetUniformLocation(\"yuvTexSampler\") = %d\n",
+            gYuvTexSamplerHandle);
+
+    glViewport(0, 0, w, h);
+    checkGlError("glViewport");
+    return true;
+}
+
+int align(int x, int a) {
+    return (x + (a-1)) & (~(a-1));
+}
+
+const int yuvTexWidth = 608;
+const int yuvTexHeight = 480;
+const int yuvTexUsage = GraphicBuffer::USAGE_HW_TEXTURE |
+        GraphicBuffer::USAGE_SW_WRITE_RARELY;
+const int yuvTexFormat = HAL_PIXEL_FORMAT_YV12;
+const int yuvTexOffsetY = 0;
+const int yuvTexStrideY = (yuvTexWidth + 0xf) & ~0xf;
+const int yuvTexOffsetV = yuvTexStrideY * yuvTexHeight;
+const int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; 
+const int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * yuvTexHeight/2;
+const int yuvTexStrideU = yuvTexStrideV;
+const bool yuvTexSameUV = false;
+static sp<GraphicBuffer> yuvTexBuffer;
+static GLuint yuvTex;
+
+bool setupYuvTexSurface(EGLDisplay dpy, EGLContext context) {
+    int blockWidth = yuvTexWidth > 16 ? yuvTexWidth / 16 : 1;
+    int blockHeight = yuvTexHeight > 16 ? yuvTexHeight / 16 : 1;
+    yuvTexBuffer = new GraphicBuffer(yuvTexWidth, yuvTexHeight, yuvTexFormat,
+            yuvTexUsage);
+    char* buf = NULL;
+    status_t err = yuvTexBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
+    if (err != 0) {
+        fprintf(stderr, "yuvTexBuffer->lock(...) failed: %d\n", err);
+        return false;
+    }
+    for (int x = 0; x < yuvTexWidth; x++) {
+        for (int y = 0; y < yuvTexHeight; y++) {
+            int parityX = (x / blockWidth) & 1;
+            int parityY = (y / blockHeight) & 1;
+            unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
+            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
+            if (x < yuvTexWidth / 2 && y < yuvTexHeight / 2) {
+                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
+                if (yuvTexSameUV) {
+                    buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] = intensity;
+                } else if (x < yuvTexWidth / 4 && y < yuvTexHeight / 4) {
+                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
+                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
+                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
+                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] = intensity;
+                }
+            }
+        }
+    }
+
+    err = yuvTexBuffer->unlock();
+    if (err != 0) {
+        fprintf(stderr, "yuvTexBuffer->unlock() failed: %d\n", err);
+        return false;
+    }
+
+    EGLClientBuffer clientBuffer = (EGLClientBuffer)yuvTexBuffer->getNativeBuffer();
+    EGLImageKHR img = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+            clientBuffer, 0);
+    checkEglError("eglCreateImageKHR");
+    if (img == EGL_NO_IMAGE_KHR) {
+        return false;
+    }
+
+    glGenTextures(1, &yuvTex);
+    checkGlError("glGenTextures");
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, yuvTex);
+    checkGlError("glBindTexture");
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)img);
+    checkGlError("glEGLImageTargetTexture2DOES");
+
+    return true;
+}
+
+const GLfloat gTriangleVertices[] = {
+    -0.5f, 0.5f,
+    -0.5f, -0.5f,
+    0.5f, -0.5f,
+    0.5f, 0.5f,
+};
+
+void renderFrame() {
+    glClearColor(0.0f, 0.0f, 1.0f, 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");
+
+    glUniform1i(gYuvTexSamplerHandle, 0);
+    checkGlError("glUniform1i");
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, yuvTex);
+    checkGlError("glBindTexture");
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+    checkGlError("glDrawArrays");
+}
+
+void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
+
+#define X(VAL) {VAL, #VAL}
+    struct {EGLint attribute; const char* name;} names[] = {
+    X(EGL_BUFFER_SIZE),
+    X(EGL_ALPHA_SIZE),
+    X(EGL_BLUE_SIZE),
+    X(EGL_GREEN_SIZE),
+    X(EGL_RED_SIZE),
+    X(EGL_DEPTH_SIZE),
+    X(EGL_STENCIL_SIZE),
+    X(EGL_CONFIG_CAVEAT),
+    X(EGL_CONFIG_ID),
+    X(EGL_LEVEL),
+    X(EGL_MAX_PBUFFER_HEIGHT),
+    X(EGL_MAX_PBUFFER_PIXELS),
+    X(EGL_MAX_PBUFFER_WIDTH),
+    X(EGL_NATIVE_RENDERABLE),
+    X(EGL_NATIVE_VISUAL_ID),
+    X(EGL_NATIVE_VISUAL_TYPE),
+    X(EGL_SAMPLES),
+    X(EGL_SAMPLE_BUFFERS),
+    X(EGL_SURFACE_TYPE),
+    X(EGL_TRANSPARENT_TYPE),
+    X(EGL_TRANSPARENT_RED_VALUE),
+    X(EGL_TRANSPARENT_GREEN_VALUE),
+    X(EGL_TRANSPARENT_BLUE_VALUE),
+    X(EGL_BIND_TO_TEXTURE_RGB),
+    X(EGL_BIND_TO_TEXTURE_RGBA),
+    X(EGL_MIN_SWAP_INTERVAL),
+    X(EGL_MAX_SWAP_INTERVAL),
+    X(EGL_LUMINANCE_SIZE),
+    X(EGL_ALPHA_MASK_SIZE),
+    X(EGL_COLOR_BUFFER_TYPE),
+    X(EGL_RENDERABLE_TYPE),
+    X(EGL_CONFORMANT),
+   };
+#undef X
+
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            printf(" %s: ", names[j].name);
+            printf("%d (0x%x)", value, value);
+        }
+    }
+    printf("\n");
+}
+
+int main(int argc, char** argv) {
+    EGLBoolean returnValue;
+    EGLConfig myConfig = {0};
+
+    EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+    EGLint s_configAttribs[] = {
+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+            EGL_NONE };
+    EGLint majorVersion;
+    EGLint minorVersion;
+    EGLContext context;
+    EGLSurface surface;
+    EGLint w, h;
+
+    EGLDisplay dpy;
+
+    checkEglError("<init>");
+    dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    checkEglError("eglGetDisplay");
+    if (dpy == EGL_NO_DISPLAY) {
+        printf("eglGetDisplay returned EGL_NO_DISPLAY.\n");
+        return 0;
+    }
+
+    returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
+    checkEglError("eglInitialize", returnValue);
+    fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
+    if (returnValue != EGL_TRUE) {
+        printf("eglInitialize failed\n");
+        return 0;
+    }
+
+    EGLNativeWindowType window = android_createDisplaySurface();
+    returnValue = EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &myConfig);
+    if (returnValue) {
+        printf("EGLUtils::selectConfigForNativeWindow() returned %d", returnValue);
+        return 1;
+    }
+
+    checkEglError("EGLUtils::selectConfigForNativeWindow");
+
+    printf("Chose this configuration:\n");
+    printEGLConfiguration(dpy, myConfig);
+
+    surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
+    checkEglError("eglCreateWindowSurface");
+    if (surface == EGL_NO_SURFACE) {
+        printf("gelCreateWindowSurface failed.\n");
+        return 1;
+    }
+
+    context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
+    checkEglError("eglCreateContext");
+    if (context == EGL_NO_CONTEXT) {
+        printf("eglCreateContext failed\n");
+        return 1;
+    }
+    returnValue = eglMakeCurrent(dpy, surface, surface, context);
+    checkEglError("eglMakeCurrent", returnValue);
+    if (returnValue != EGL_TRUE) {
+        return 1;
+    }
+    eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+    checkEglError("eglQuerySurface");
+    eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+    checkEglError("eglQuerySurface");
+    GLint dim = w < h ? w : h;
+
+    fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
+
+    printGLString("Version", GL_VERSION);
+    printGLString("Vendor", GL_VENDOR);
+    printGLString("Renderer", GL_RENDERER);
+    printGLString("Extensions", GL_EXTENSIONS);
+
+    if(!setupYuvTexSurface(dpy, context)) {
+        fprintf(stderr, "Could not set up texture surface.\n");
+        return 1;
+    }
+
+    if(!setupGraphics(w, h)) {
+        fprintf(stderr, "Could not set up graphics.\n");
+        return 1;
+    }
+
+    for (;;) {
+        renderFrame();
+        eglSwapBuffers(dpy, surface);
+        checkEglError("eglSwapBuffers");
+    }
+
+    return 0;
+}
diff --git a/opengl/tests/gl_yuvtex/Android.mk b/opengl/tests/gl_yuvtex/Android.mk
new file mode 100644
index 0000000..a78db25
--- /dev/null
+++ b/opengl/tests/gl_yuvtex/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	gl_yuvtex.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv1_CM \
+    libui
+
+LOCAL_MODULE:= test-opengl-gl_yuvtex
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl_yuvtex/gl_yuvtex.cpp b/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
new file mode 100644
index 0000000..fbe65f1
--- /dev/null
+++ b/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sched.h>
+#include <sys/resource.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/Timers.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+static void printGLString(const char *name, GLenum s) {
+    // fprintf(stderr, "printGLString %s, %d\n", name, s);
+    const char *v = (const char *) glGetString(s);
+    // int error = glGetError();
+    // fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error,
+    //        (unsigned int) v);
+    // if ((v < (const char*) 0) || (v > (const char*) 0x10000))
+    //    fprintf(stderr, "GL %s = %s\n", name, v);
+    // else
+    //    fprintf(stderr, "GL %s = (null) 0x%08x\n", name, (unsigned int) v);
+    fprintf(stderr, "GL %s = %s\n", name, v);
+}
+
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+    if (returnVal != EGL_TRUE) {
+        fprintf(stderr, "%s() returned %d\n", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+            = eglGetError()) {
+        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
+                error);
+    }
+}
+
+static void checkGlError(const char* op) {
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
+    }
+}
+
+bool setupGraphics(int w, int h) {
+    glViewport(0, 0, w, h);
+    checkGlError("glViewport");
+    return true;
+}
+
+int align(int x, int a) {
+    return (x + (a-1)) & (~(a-1));
+}
+
+const int yuvTexWidth = 600;
+const int yuvTexHeight = 480;
+const int yuvTexUsage = GraphicBuffer::USAGE_HW_TEXTURE |
+        GraphicBuffer::USAGE_SW_WRITE_RARELY;
+const int yuvTexFormat = HAL_PIXEL_FORMAT_YV12;
+const int yuvTexOffsetY = 0;
+const int yuvTexStrideY = (yuvTexWidth + 0xf) & ~0xf;
+const int yuvTexOffsetV = yuvTexStrideY * yuvTexHeight;
+const int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; 
+const int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * yuvTexHeight/2;
+const int yuvTexStrideU = yuvTexStrideV;
+const bool yuvTexSameUV = false;
+static sp<GraphicBuffer> yuvTexBuffer;
+static GLuint yuvTex;
+
+bool setupYuvTexSurface(EGLDisplay dpy, EGLContext context) {
+    int blockWidth = yuvTexWidth > 16 ? yuvTexWidth / 16 : 1;
+    int blockHeight = yuvTexHeight > 16 ? yuvTexHeight / 16 : 1;
+    yuvTexBuffer = new GraphicBuffer(yuvTexWidth, yuvTexHeight, yuvTexFormat,
+            yuvTexUsage);
+    char* buf = NULL;
+    status_t err = yuvTexBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
+    if (err != 0) {
+        fprintf(stderr, "yuvTexBuffer->lock(...) failed: %d\n", err);
+        return false;
+    }
+    for (int x = 0; x < yuvTexWidth; x++) {
+        for (int y = 0; y < yuvTexHeight; y++) {
+            int parityX = (x / blockWidth) & 1;
+            int parityY = (y / blockHeight) & 1;
+            unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
+            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
+            if (x < yuvTexWidth / 2 && y < yuvTexHeight / 2) {
+                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
+                if (yuvTexSameUV) {
+                    buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] = intensity;
+                } else if (x < yuvTexWidth / 4 && y < yuvTexHeight / 4) {
+                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
+                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
+                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
+                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] = intensity;
+                }
+            }
+        }
+    }
+
+    err = yuvTexBuffer->unlock();
+    if (err != 0) {
+        fprintf(stderr, "yuvTexBuffer->unlock() failed: %d\n", err);
+        return false;
+    }
+
+    EGLClientBuffer clientBuffer = (EGLClientBuffer)yuvTexBuffer->getNativeBuffer();
+    EGLImageKHR img = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+            clientBuffer, 0);
+    checkEglError("eglCreateImageKHR");
+    if (img == EGL_NO_IMAGE_KHR) {
+        return false;
+    }
+
+    glGenTextures(1, &yuvTex);
+    checkGlError("glGenTextures");
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, yuvTex);
+    checkGlError("glBindTexture");
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)img);
+    checkGlError("glEGLImageTargetTexture2DOES");
+    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    checkGlError("glTexParameteri");
+    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    checkGlError("glTexParameteri");
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    checkGlError("glTexEnvx");
+
+    GLint crop[4] = { 0, 0, yuvTexWidth, yuvTexHeight };
+    glTexParameteriv(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_CROP_RECT_OES, crop);
+    checkGlError("glTexParameteriv");
+
+    return true;
+}
+
+void renderFrame(int w, int h) {
+    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+    checkGlError("glClearColor");
+    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    checkGlError("glClear");
+    
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, yuvTex);
+    checkGlError("glBindTexture");
+    glEnable(GL_TEXTURE_EXTERNAL_OES);
+    checkGlError("glEnable");
+
+    glDrawTexiOES(0, 0, 0, w, h);
+    checkGlError("glDrawTexiOES");
+}
+
+void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
+
+#define X(VAL) {VAL, #VAL}
+    struct {EGLint attribute; const char* name;} names[] = {
+    X(EGL_BUFFER_SIZE),
+    X(EGL_ALPHA_SIZE),
+    X(EGL_BLUE_SIZE),
+    X(EGL_GREEN_SIZE),
+    X(EGL_RED_SIZE),
+    X(EGL_DEPTH_SIZE),
+    X(EGL_STENCIL_SIZE),
+    X(EGL_CONFIG_CAVEAT),
+    X(EGL_CONFIG_ID),
+    X(EGL_LEVEL),
+    X(EGL_MAX_PBUFFER_HEIGHT),
+    X(EGL_MAX_PBUFFER_PIXELS),
+    X(EGL_MAX_PBUFFER_WIDTH),
+    X(EGL_NATIVE_RENDERABLE),
+    X(EGL_NATIVE_VISUAL_ID),
+    X(EGL_NATIVE_VISUAL_TYPE),
+    X(EGL_SAMPLES),
+    X(EGL_SAMPLE_BUFFERS),
+    X(EGL_SURFACE_TYPE),
+    X(EGL_TRANSPARENT_TYPE),
+    X(EGL_TRANSPARENT_RED_VALUE),
+    X(EGL_TRANSPARENT_GREEN_VALUE),
+    X(EGL_TRANSPARENT_BLUE_VALUE),
+    X(EGL_BIND_TO_TEXTURE_RGB),
+    X(EGL_BIND_TO_TEXTURE_RGBA),
+    X(EGL_MIN_SWAP_INTERVAL),
+    X(EGL_MAX_SWAP_INTERVAL),
+    X(EGL_LUMINANCE_SIZE),
+    X(EGL_ALPHA_MASK_SIZE),
+    X(EGL_COLOR_BUFFER_TYPE),
+    X(EGL_RENDERABLE_TYPE),
+    X(EGL_CONFORMANT),
+   };
+#undef X
+
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            printf(" %s: ", names[j].name);
+            printf("%d (0x%x)", value, value);
+        }
+    }
+    printf("\n");
+}
+
+int main(int argc, char** argv) {
+    EGLBoolean returnValue;
+    EGLConfig myConfig = {0};
+
+    EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
+    EGLint s_configAttribs[] = {
+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+            EGL_NONE };
+    EGLint majorVersion;
+    EGLint minorVersion;
+    EGLContext context;
+    EGLSurface surface;
+    EGLint w, h;
+
+    EGLDisplay dpy;
+
+    checkEglError("<init>");
+    dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    checkEglError("eglGetDisplay");
+    if (dpy == EGL_NO_DISPLAY) {
+        printf("eglGetDisplay returned EGL_NO_DISPLAY.\n");
+        return 0;
+    }
+
+    returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
+    checkEglError("eglInitialize", returnValue);
+    fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
+    if (returnValue != EGL_TRUE) {
+        printf("eglInitialize failed\n");
+        return 0;
+    }
+
+    EGLNativeWindowType window = android_createDisplaySurface();
+    returnValue = EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &myConfig);
+    if (returnValue) {
+        printf("EGLUtils::selectConfigForNativeWindow() returned %d", returnValue);
+        return 1;
+    }
+
+    checkEglError("EGLUtils::selectConfigForNativeWindow");
+
+    printf("Chose this configuration:\n");
+    printEGLConfiguration(dpy, myConfig);
+
+    surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
+    checkEglError("eglCreateWindowSurface");
+    if (surface == EGL_NO_SURFACE) {
+        printf("gelCreateWindowSurface failed.\n");
+        return 1;
+    }
+
+    context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
+    checkEglError("eglCreateContext");
+    if (context == EGL_NO_CONTEXT) {
+        printf("eglCreateContext failed\n");
+        return 1;
+    }
+    returnValue = eglMakeCurrent(dpy, surface, surface, context);
+    checkEglError("eglMakeCurrent", returnValue);
+    if (returnValue != EGL_TRUE) {
+        return 1;
+    }
+    eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+    checkEglError("eglQuerySurface");
+    eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+    checkEglError("eglQuerySurface");
+    GLint dim = w < h ? w : h;
+
+    fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
+
+    printGLString("Version", GL_VERSION);
+    printGLString("Vendor", GL_VENDOR);
+    printGLString("Renderer", GL_RENDERER);
+    printGLString("Extensions", GL_EXTENSIONS);
+
+    if(!setupYuvTexSurface(dpy, context)) {
+        fprintf(stderr, "Could not set up texture surface.\n");
+        return 1;
+    }
+
+    if(!setupGraphics(w, h)) {
+        fprintf(stderr, "Could not set up graphics.\n");
+        return 1;
+    }
+
+    for (;;) {
+        static int dir = -1;
+
+        renderFrame(w, h);
+        eglSwapBuffers(dpy, surface);
+        checkEglError("eglSwapBuffers");
+
+        if (w <= 10 || h <= 10)
+        {
+            dir = -dir;
+        }
+
+        if (w >= 1300 || h >= 900)
+        {
+            dir = -dir;
+        }
+
+
+        w += dir;
+        h += dir;
+    }
+
+    return 0;
+}
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png b/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
new file mode 100644
index 0000000..e74c22f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notification_peek.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notification_peek.xml
new file mode 100644
index 0000000..a7c91f5
--- /dev/null
+++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notification_peek.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** 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.
+*/
+-->
+
+<!--    android:background="@drawable/status_bar_closed_default_background" -->
+<com.android.systemui.statusbar.tablet.NotificationPanel
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:background="@*android:drawable/dialog_full_holo_dark"
+    android:orientation="vertical"
+    >
+
+    <FrameLayout 
+        android:id="@+id/content"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_horizontal|bottom"
+        android:animationCache="false"
+        android:orientation="vertical"
+        android:background="@drawable/status_bar_background"
+        android:clickable="true"
+        android:focusable="true"
+        android:descendantFocusability="afterDescendants"
+        >
+    </FrameLayout>
+</com.android.systemui.statusbar.tablet.NotificationPanel>
diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml
index 80c9a49..8cbf3e3 100644
--- a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml
+++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml
@@ -23,20 +23,23 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
-    android:background="#FF000000"
+    android:background="@*android:drawable/dialog_full_holo_dark"
     android:orientation="vertical"
+    android:animateLayoutChanges="true"
     >
 
     <ScrollView
         android:id="@+id/notificationScroller"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
+        android:animateLayoutChanges="true"
         >
         <LinearLayout 
             android:id="@+id/content"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:gravity="center_horizontal|bottom"
+            android:animateLayoutChanges="true"
             android:animationCache="false"
             android:orientation="vertical"
             android:background="@drawable/status_bar_background"
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index ff59db0..8785498 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Vymazat"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Žádná oznámení"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Probíhající"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Oznámení"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Baterie je vybitá:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"Zbývá <xliff:g id="NUMBER">%d%%</xliff:g> nebo méně."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Využití baterie"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Nejnovější"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 9389617..fe96883 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ryd"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen meddelelser"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"I gang"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelelser"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteriet er ved at være fladt:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> eller mindre tilbage."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Batteriforbrug"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Seneste"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 3ea65d9..5338ab2 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Löschen"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Keine Benachrichtigungen"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktuell"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Benachrichtigungen"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Akku ist fast leer."</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> oder weniger verbleiben."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Akkuverbrauch"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Zuletzt verwendet"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index cba1047..23db1d4 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Εκκαθάριση"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Δεν υπάρχουν ειδοποιήσεις"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Εν εξελίξει"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ειδοποιήσεις"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Η στάθμη της μπαταρίας είναι χαμηλή:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"Απομένει <xliff:g id="NUMBER">%d%%</xliff:g> ή λιγότερο."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Χρήση μπαταρίας"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Πρόσφατα"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 56dead5..c539856 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No hay notificaciones"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continuo"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Hay poca batería:"</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>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Reciente"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 4ebe492..569cef0 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No tienes notificaciones"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Entrante"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Se está agotando la batería:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> o menos disponible"</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Uso de la batería"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Reciente"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7aff506..b6b493f 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Effacer"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Aucune notification"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Le niveau de la batterie est bas :"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"Maximum <xliff:g id="NUMBER">%d%%</xliff:g> restants."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Utilisation de la batterie"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Récentes"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 496a82e..03f63db 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Cancella"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nessuna notifica"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"In corso"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifiche"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteria quasi scarica:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> rimanente o meno."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Utilizzo batteria"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Recenti"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 24c018b..65cf46d 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"通知を消去"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"通知なし"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"実行中"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"電池が残り少なくなっています:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"残り<xliff:g id="NUMBER">%d%%</xliff:g>未満です。"</string>
     <string name="battery_low_why" msgid="7279169609518386372">"電池使用量"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"新着"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 0b6649d..988a7c5 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"지우기"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"알림 없음"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"진행 중"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"알림"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"배터리 전원이 부족합니다."</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"잔여 배터리가 <xliff:g id="NUMBER">%d%%</xliff:g> 이하입니다."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"배터리 사용량"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"최근 사용한 앱"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 5684e57..43b6aed 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Fjern"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen varslinger"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktiviteter"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varslinger"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteriet er nesten tomt:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"mindre enn <xliff:g id="NUMBER">%d%%</xliff:g> igjen."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Batteribruk"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Nylig"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index cd10b29..ce066d5 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Wissen"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Geen meldingen"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Actief"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meldingen"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"De accu raakt op:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> of minder resterend."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Accugebruik"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Recent"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 70f3ad2..69d93f9 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Wyczyść"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Brak powiadomień"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Bieżące"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Powiadomienia"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Bateria się rozładowuje:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"Pozostało: <xliff:g id="NUMBER">%d%%</xliff:g> lub mniej."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Użycie baterii"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Najnowsze"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 492063a9..e8f93a2 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Limpar"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em curso"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"A bateria está a ficar fraca:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"Restam <xliff:g id="NUMBER">%d%%</xliff:g> ou menos."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Utilização da bateria"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 08effa7..6dbbfb4 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Limpar"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em andamento"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"A bateria está ficando baixa:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> ou menos restante(s)."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Uso da bateria"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 7c5bcf7..5296e8c 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Очистить"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Нет уведомлений"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текущие"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Уведомления"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Батарея разряжена:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"Осталось <xliff:g id="NUMBER">%d%%</xliff:g> или меньше."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Расход заряда батареи"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Недавние"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 1127c9d..4b4efe6 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ta bort"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Inga aviseringar"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Pågående"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelanden"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteriet håller på att ta slut:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> eller mindre kvar."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Batteriförbrukning"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"Senaste"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index dd66d82..2783262 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Temizle"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Bildirim yok"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sürüyor"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirimler"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"Pil tükeniyor:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> veya daha az kaldı."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Pil kullanımı"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"En Son Görevler"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index cda0317..958c051 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"无通知"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"正在进行的"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"电量所剩不多:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"电量剩余 <xliff:g id="NUMBER">%d%%</xliff:g> 或更少。"</string>
     <string name="battery_low_why" msgid="7279169609518386372">"电量使用情况"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"近期任务"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 503087b..c4ecc32 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -22,6 +22,10 @@
     <!-- no translation found for app_label (4489004083283879149) -->
     <skip />
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
+    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
+    <skip />
+    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
+    <skip />
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"沒有通知"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"進行中"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
@@ -29,4 +33,9 @@
     <string name="battery_low_subtitle" msgid="7388781709819722764">"電池電量即將不足:"</string>
     <string name="battery_low_percent_format" msgid="696154104579022959">"還剩 <xliff:g id="NUMBER">%d%%</xliff:g> 以下。"</string>
     <string name="battery_low_why" msgid="7279169609518386372">"電池使用狀況"</string>
+    <!-- no translation found for system_panel_settings_button (7832600575390861653) -->
+    <skip />
+    <string name="recent_tasks_title" msgid="3691764623638127888">"最新的"</string>
+    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 1f24ba6..701aa9f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -53,11 +53,17 @@
     <string name="battery_low_title">Please connect charger</string>
 
     <!-- When the battery is low, this is displayed to the user in a dialog. The subtitle of the low battery alert. -->
-    <string name="battery_low_subtitle">The battery is getting low:</string>
+    <string name="battery_low_subtitle">The battery is getting low.</string>
 
-    <!-- A message that appears when the battery level is getting low in a dialog.  This is appened to the subtitle of the low battery alert. -->
-    <string name="battery_low_percent_format"><xliff:g id="number">%d%%</xliff:g>
-    or less remaining.</string>
+    <!-- A message that appears when the battery level is getting low in a dialog.  This is
+        appened to the subtitle of the low battery alert. -->
+    <string name="battery_low_percent_format"><xliff:g id="number">%d%%</xliff:g> remaining</string>
+
+    <!-- A message that appears when a USB charger is plugged in and the device does not
+    support charging on it.  That is, a charger that fits into the USB port and goes into
+    a wall socket, not into a computer. (This happens because some devices require more
+    current than the USB spec allows.  -->
+    <string name="invalid_charger">USB charging not supported.\nUse only the supplied charger.</string>
 
     <!-- When the battery is low, this is the label of the button to go to the
          power usage activity to find out what drained the battery. -->
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index dda86d2..65990ad 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -36,6 +36,7 @@
      */
     final Object[] SERVICES = new Object[] {
             R.string.config_statusBarComponent,
+            com.android.systemui.power.PowerUI.class,
         };
 
     /**
@@ -96,9 +97,19 @@
             return;
         }
 
-        for (SystemUI ui: mServices) {
-            pw.println("dumping service: " + ui.getClass().getName());
-            ui.dump(fd, pw, args);
+        if (args == null || args.length == 0) {
+            for (SystemUI ui: mServices) {
+                pw.println("dumping service: " + ui.getClass().getName());
+                ui.dump(fd, pw, args);
+            }
+        } else {
+            String svc = args[0];
+            for (SystemUI ui: mServices) {
+                String name = ui.getClass().getName();
+                if (name.endsWith(svc)) {
+                    ui.dump(fd, pw, args);
+                }
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
new file mode 100644
index 0000000..aeb8d3c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.power;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.BatteryManager;
+import android.os.Handler;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.provider.Settings;
+import android.util.Slog;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+
+public class PowerUI extends SystemUI {
+    static final String TAG = "PowerUI";
+
+    Handler mHandler = new Handler();
+
+    int mBatteryLevel = 100;
+    int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
+    int mPlugType = 0;
+    int mInvalidCharger = 0;
+
+    int mLowBatteryAlertCloseLevel;
+    int[] mLowBatteryReminderLevels = new int[2];
+
+    AlertDialog mInvalidChargerDialog;
+    AlertDialog mLowBatteryDialog;
+    TextView mBatteryLevelTextView;
+
+    public void start() {
+
+        mLowBatteryAlertCloseLevel = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);
+        mLowBatteryReminderLevels[0] = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_lowBatteryWarningLevel);
+        mLowBatteryReminderLevels[1] = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_criticalBatteryWarningLevel);
+
+        // Register for Intent broadcasts for...
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        filter.addAction(Intent.ACTION_POWER_CONNECTED);
+        mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
+    }
+
+    /**
+     * Buckets the battery level.
+     *
+     * The code in this function is a little weird because I couldn't comprehend
+     * the bucket going up when the battery level was going down. --joeo
+     *
+     * 1 means that the battery is "ok"
+     * 0 means that the battery is between "ok" and what we should warn about.
+     * less than 0 means that the battery is low
+     */
+    private int findBatteryLevelBucket(int level) {
+        if (level >= mLowBatteryAlertCloseLevel) {
+            return 1;
+        }
+        if (level >= mLowBatteryReminderLevels[0]) {
+            return 0;
+        }
+        final int N = mLowBatteryReminderLevels.length;
+        for (int i=N-1; i>=0; i--) {
+            if (level <= mLowBatteryReminderLevels[i]) {
+                return -1-i;
+            }
+        }
+        throw new RuntimeException("not possible!");
+    }
+
+    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+                final int oldBatteryLevel = mBatteryLevel;
+                mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);
+                final int oldBatteryStatus = mBatteryStatus;
+                mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
+                        BatteryManager.BATTERY_STATUS_UNKNOWN);
+                final int oldPlugType = mPlugType;
+                mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
+                final int oldInvalidCharger = mInvalidCharger;
+                mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
+
+                final boolean plugged = mPlugType != 0;
+                final boolean oldPlugged = oldPlugType != 0;
+
+                int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
+                int bucket = findBatteryLevelBucket(mBatteryLevel);
+
+                if (false) {
+                    Slog.d(TAG, "buckets   ....." + mLowBatteryAlertCloseLevel
+                            + " .. " + mLowBatteryReminderLevels[0]
+                            + " .. " + mLowBatteryReminderLevels[1]);
+                    Slog.d(TAG, "level          " + oldBatteryLevel + " --> " + mBatteryLevel);
+                    Slog.d(TAG, "status         " + oldBatteryStatus + " --> " + mBatteryStatus);
+                    Slog.d(TAG, "plugType       " + oldPlugType + " --> " + mPlugType);
+                    Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
+                    Slog.d(TAG, "bucket         " + oldBucket + " --> " + bucket);
+                    Slog.d(TAG, "plugged        " + oldPlugged + " --> " + plugged);
+                }
+
+                if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
+                    Slog.d(TAG, "showing invalid charger warning");
+                    showInvalidChargerDialog();
+                    return;
+                } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
+                    Slog.d(TAG, "closing invalid charger warning");
+                    dismissInvalidChargerDialog();
+                } else if (mInvalidChargerDialog != null) {
+                    // if invalid charger is showing, don't show low battery
+                    return;
+                }
+
+                if (!plugged
+                        && (bucket < oldBucket || oldPlugged)
+                        && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
+                        && bucket < 0) {
+                    Slog.d(TAG, "showing low battery warning: level=" + mBatteryLevel);
+                    showLowBatteryWarning();
+                } else if (plugged || (bucket > oldBucket && bucket > 0)) {
+                    Slog.d(TAG, "closing low battery warning: level=" + mBatteryLevel);
+                    dismissLowBatteryWarning();
+                } else if (mBatteryLevelTextView != null) {
+                    showLowBatteryWarning();
+                }
+            } else {
+                Slog.w(TAG, "unknown intent: " + intent);
+            }
+        }
+    };
+
+    void dismissLowBatteryWarning() {
+        if (mLowBatteryDialog != null) {
+            mLowBatteryDialog.dismiss();
+        }
+    }
+
+    void showLowBatteryWarning() {
+        CharSequence levelText = mContext.getString(
+                R.string.battery_low_percent_format, mBatteryLevel);
+
+        if (mBatteryLevelTextView != null) {
+            mBatteryLevelTextView.setText(levelText);
+        } else {
+            View v = View.inflate(mContext, R.layout.battery_low, null);
+            mBatteryLevelTextView = (TextView)v.findViewById(R.id.level_percent);
+
+            mBatteryLevelTextView.setText(levelText);
+
+            AlertDialog.Builder b = new AlertDialog.Builder(mContext);
+                b.setCancelable(true);
+                b.setTitle(R.string.battery_low_title);
+                b.setView(v);
+                b.setIcon(android.R.drawable.ic_dialog_alert);
+                b.setPositiveButton(android.R.string.ok, null);
+
+            final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+                    | Intent.FLAG_ACTIVITY_NO_HISTORY);
+            if (intent.resolveActivity(mContext.getPackageManager()) != null) {
+                b.setNegativeButton(R.string.battery_low_why,
+                        new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        mContext.startActivity(intent);
+                        if (mLowBatteryDialog != null) {
+                            mLowBatteryDialog.dismiss();
+                        }
+                    }
+                });
+            }
+
+            AlertDialog d = b.create();
+            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                    public void onDismiss(DialogInterface dialog) {
+                        mLowBatteryDialog = null;
+                        mBatteryLevelTextView = null;
+                    }
+                });
+            d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+            d.show();
+            mLowBatteryDialog = d;
+        }
+
+if (false) { // getRingtone ANRs
+        final ContentResolver cr = mContext.getContentResolver();
+        if (Settings.System.getInt(cr, Settings.System.POWER_SOUNDS_ENABLED, 1) == 1) {
+            final String soundPath = Settings.System.getString(cr,
+                    Settings.System.LOW_BATTERY_SOUND);
+            if (soundPath != null) {
+                final Uri soundUri = Uri.parse("file://" + soundPath);
+                if (soundUri != null) {
+                    final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+                    if (sfx != null) {
+                        sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+                        sfx.play();
+                    }
+                }
+            }
+        }
+}
+    }
+
+    void dismissInvalidChargerDialog() {
+        if (mInvalidChargerDialog != null) {
+            mInvalidChargerDialog.dismiss();
+        }
+    }
+
+    void showInvalidChargerDialog() {
+        dismissLowBatteryWarning();
+
+        AlertDialog.Builder b = new AlertDialog.Builder(mContext);
+            b.setCancelable(true);
+            b.setMessage(mContext.getString(R.string.invalid_charger));
+            b.setIcon(android.R.drawable.ic_dialog_alert);
+            b.setPositiveButton(android.R.string.ok, null);
+
+        AlertDialog d = b.create();
+            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                    public void onDismiss(DialogInterface dialog) {
+                        mInvalidChargerDialog = null;
+                        mBatteryLevelTextView = null;
+                    }
+                });
+
+        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        d.show();
+        mInvalidChargerDialog = d;
+    }
+    
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.print("mLowBatteryAlertCloseLevel=");
+        pw.println(mLowBatteryAlertCloseLevel);
+        pw.print("mLowBatteryReminderLevels=");
+        pw.println(Arrays.toString(mLowBatteryReminderLevels));
+        pw.print("mInvalidChargerDialog=");
+        pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString());
+        pw.print("mLowBatteryDialog=");
+        pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
+        pw.print("mBatteryLevel=");
+        pw.println(Integer.toString(mBatteryLevel));
+        pw.print("mBatteryStatus=");
+        pw.println(Integer.toString(mBatteryStatus));
+        pw.print("mPlugType=");
+        pw.println(Integer.toString(mPlugType));
+        pw.print("mInvalidCharger=");
+        pw.println(Integer.toString(mInvalidCharger));
+        pw.print("bucket: ");
+        pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
+    }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index c164eb4..ed2ed1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -55,6 +55,7 @@
     private static final int MSG_SET_LIGHTS_ON = 0x00070000;
 
     private static final int MSG_SHOW_MENU = 0x00080000;
+    private static final int MSG_SHOW_IME_BUTTON = 0x00090000;
 
     private StatusBarIconList mList;
     private Callbacks mCallbacks;
@@ -81,6 +82,7 @@
         public void animateCollapse();
         public void setLightsOn(boolean on);
         public void setMenuKeyVisible(boolean visible);
+        public void setIMEButtonVisible(boolean visible);
     }
 
     public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -163,6 +165,13 @@
         }
     }
 
+    public void setIMEButtonVisible(boolean visible) {
+        synchronized (mList) {
+            mHandler.removeMessages(MSG_SHOW_IME_BUTTON);
+            mHandler.obtainMessage(MSG_SHOW_IME_BUTTON, visible ? 1 : 0, 0, null).sendToTarget();
+        }
+    }
+
     private final class H extends Handler {
         public void handleMessage(Message msg) {
             final int what = msg.what & MSG_MASK;
@@ -223,6 +232,9 @@
                 case MSG_SHOW_MENU:
                     mCallbacks.setMenuKeyVisible(msg.arg1 != 0);
                     break;
+                case MSG_SHOW_IME_BUTTON:
+                    mCallbacks.setIMEButtonVisible(msg.arg1 != 0);
+                    break;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
index bf58b37..b174973 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
@@ -1014,6 +1014,7 @@
 
     // Not supported
     public void setMenuKeyVisible(boolean visible) { }
+    public void setIMEButtonVisible(boolean visible) { }
 
     private class Launcher implements View.OnClickListener {
         private PendingIntent mIntent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
index fb74e70..a03a0ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
@@ -17,14 +17,11 @@
 package com.android.systemui.statusbar.policy;
 
 import android.app.StatusBarManager;
-import android.app.AlertDialog;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothPbap;
 import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.TypedArray;
@@ -33,8 +30,6 @@
 import android.graphics.drawable.Drawable;
 import android.location.LocationManager;
 import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
@@ -59,11 +54,8 @@
 import android.util.Slog;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.IccCard;
@@ -95,24 +87,12 @@
 
     private final Context mContext;
     private final StatusBarManager mService;
-    private final Handler mHandler = new StatusBarHandler();
+    private final Handler mHandler = new Handler();
     private final IBatteryStats mBatteryStats;
 
     // storage
     private StorageManager mStorageManager;
 
-    // battery
-    private boolean mBatteryFirst = true;
-    private boolean mBatteryPlugged;
-    private int mBatteryLevel;
-    private AlertDialog mLowBatteryDialog;
-    private TextView mBatteryLevelTextView;
-    private View mBatteryView;
-    private int mBatteryViewSequence;
-    private boolean mBatteryShowLowOnEndCall = false;
-    private static final boolean SHOW_LOW_BATTERY_WARNING = true;
-    private static final boolean SHOW_BATTERY_WARNINGS_IN_CALL = true;
-
     // phone
     private TelephonyManager mPhone;
     private int mPhoneSignalIconId;
@@ -357,13 +337,6 @@
             else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
                 updateSyncState(intent);
             }
-            else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
-                onBatteryLow(intent);
-            }
-            else if (action.equals(Intent.ACTION_BATTERY_OKAY)
-                    || action.equals(Intent.ACTION_POWER_CONNECTED)) {
-                onBatteryOkay(intent);
-            }
             else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
                     action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
                 updateBluetooth(intent);
@@ -473,9 +446,6 @@
 
         // Register for Intent broadcasts for...
         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
-        filter.addAction(Intent.ACTION_BATTERY_LOW);
-        filter.addAction(Intent.ACTION_BATTERY_OKAY);
-        filter.addAction(Intent.ACTION_POWER_CONNECTED);
         filter.addAction(Intent.ACTION_ALARM_CHANGED);
         filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
@@ -520,179 +490,6 @@
         final int id = intent.getIntExtra("icon-small", 0);
         int level = intent.getIntExtra("level", 0);
         mService.setIcon("battery", id, level);
-
-        boolean plugged = intent.getIntExtra("plugged", 0) != 0;
-        level = intent.getIntExtra("level", -1);
-        if (false) {
-            Slog.d(TAG, "updateBattery level=" + level
-                    + " plugged=" + plugged
-                    + " mBatteryPlugged=" + mBatteryPlugged
-                    + " mBatteryLevel=" + mBatteryLevel
-                    + " mBatteryFirst=" + mBatteryFirst);
-        }
-
-        boolean oldPlugged = mBatteryPlugged;
-
-        mBatteryPlugged = plugged;
-        mBatteryLevel = level;
-
-        if (mBatteryFirst) {
-            mBatteryFirst = false;
-        }
-        /*
-         * No longer showing the battery view because it draws attention away
-         * from the USB storage notification. We could still show it when
-         * connected to a brick, but that could lead to the user into thinking
-         * the device does not charge when plugged into USB (since he/she would
-         * not see the same battery screen on USB as he sees on brick).
-         */
-        if (false) {
-            Slog.d(TAG, "plugged=" + plugged + " oldPlugged=" + oldPlugged + " level=" + level);
-        }
-    }
-
-    private void onBatteryLow(Intent intent) {
-        if (SHOW_LOW_BATTERY_WARNING) {
-            if (false) {
-                Slog.d(TAG, "mPhoneState=" + mPhoneState
-                      + " mLowBatteryDialog=" + mLowBatteryDialog
-                      + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
-            }
-
-            if (SHOW_BATTERY_WARNINGS_IN_CALL || mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
-                showLowBatteryWarning();
-            } else {
-                mBatteryShowLowOnEndCall = true;
-            }
-        }
-    }
-
-    private void onBatteryOkay(Intent intent) {
-        if (mLowBatteryDialog != null
-                && SHOW_LOW_BATTERY_WARNING) {
-            mLowBatteryDialog.dismiss();
-            mBatteryShowLowOnEndCall = false;
-        }
-    }
-
-    private void setBatteryLevel(View parent, int id, int height, int background, int level) {
-        ImageView v = (ImageView)parent.findViewById(id);
-        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)v.getLayoutParams();
-        lp.weight = height;
-        if (background != 0) {
-            v.setBackgroundResource(background);
-            Drawable bkg = v.getBackground();
-            bkg.setLevel(level);
-        }
-    }
-
-    private void showLowBatteryWarning() {
-        closeLastBatteryView();
-
-        // Show exact battery level.
-        CharSequence levelText = mContext.getString(
-                    R.string.battery_low_percent_format, mBatteryLevel);
-
-        if (mBatteryLevelTextView != null) {
-            mBatteryLevelTextView.setText(levelText);
-        } else {
-            View v = View.inflate(mContext, R.layout.battery_low, null);
-            mBatteryLevelTextView=(TextView)v.findViewById(R.id.level_percent);
-
-            mBatteryLevelTextView.setText(levelText);
-
-            AlertDialog.Builder b = new AlertDialog.Builder(mContext);
-                b.setCancelable(true);
-                b.setTitle(R.string.battery_low_title);
-                b.setView(v);
-                b.setIcon(android.R.drawable.ic_dialog_alert);
-                b.setPositiveButton(android.R.string.ok, null);
-
-                final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
-                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                        | Intent.FLAG_ACTIVITY_NO_HISTORY);
-                if (intent.resolveActivity(mContext.getPackageManager()) != null) {
-                    b.setNegativeButton(R.string.battery_low_why,
-                            new DialogInterface.OnClickListener() {
-                        public void onClick(DialogInterface dialog, int which) {
-                            mContext.startActivity(intent);
-                            if (mLowBatteryDialog != null) {
-                                mLowBatteryDialog.dismiss();
-                            }
-                        }
-                    });
-                }
-
-            AlertDialog d = b.create();
-            d.setOnDismissListener(mLowBatteryListener);
-            d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-            d.show();
-            mLowBatteryDialog = d;
-        }
-
-        final ContentResolver cr = mContext.getContentResolver();
-        if (Settings.System.getInt(cr,
-                Settings.System.POWER_SOUNDS_ENABLED, 1) == 1)
-        {
-            final String soundPath = Settings.System.getString(cr,
-                Settings.System.LOW_BATTERY_SOUND);
-            if (soundPath != null) {
-                final Uri soundUri = Uri.parse("file://" + soundPath);
-                if (soundUri != null) {
-                    final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
-                    if (sfx != null) {
-                        sfx.setStreamType(AudioManager.STREAM_SYSTEM);
-                        sfx.play();
-                    }
-                }
-            }
-        }
-    }
-
-    private final void updateCallState(int state) {
-        mPhoneState = state;
-        if (false) {
-            Slog.d(TAG, "mPhoneState=" + mPhoneState
-                    + " mLowBatteryDialog=" + mLowBatteryDialog
-                    + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
-        }
-        if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
-            if (mBatteryShowLowOnEndCall) {
-                if (!mBatteryPlugged) {
-                    showLowBatteryWarning();
-                }
-                mBatteryShowLowOnEndCall = false;
-            }
-        } else {
-            if (mLowBatteryDialog != null) {
-                mLowBatteryDialog.dismiss();
-                mBatteryShowLowOnEndCall = true;
-            }
-        }
-    }
-
-    private DialogInterface.OnDismissListener mLowBatteryListener
-            = new DialogInterface.OnDismissListener() {
-        public void onDismiss(DialogInterface dialog) {
-            mLowBatteryDialog = null;
-            mBatteryLevelTextView = null;
-        }
-    };
-
-    private void scheduleCloseBatteryView() {
-        Message m = mHandler.obtainMessage(EVENT_BATTERY_CLOSE);
-        m.arg1 = (++mBatteryViewSequence);
-        mHandler.sendMessageDelayed(m, 3000);
-    }
-
-    private void closeLastBatteryView() {
-        if (mBatteryView != null) {
-            //mBatteryView.debug();
-            WindowManagerImpl.getDefault().removeView(mBatteryView);
-            mBatteryView = null;
-        }
     }
 
     private void updateConnectivity(Intent intent) {
@@ -753,7 +550,6 @@
 
         @Override
         public void onCallStateChanged(int state, String incomingNumber) {
-            updateCallState(state);
             // In cdma, if a voice call is made, RSSI should switch to 1x.
             if (isCdma()) {
                 updateSignalStrength();
@@ -1181,18 +977,4 @@
         }
         mService.setIcon("phone_signal", mPhoneSignalIconId, 0);
     }
-
-
-    private class StatusBarHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-            case EVENT_BATTERY_CLOSE:
-                if (msg.arg1 == mBatteryViewSequence) {
-                    closeLastBatteryView();
-                }
-                break;
-            }
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index ae1fdbd..256386b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -65,7 +65,7 @@
         mCommandQueue = new CommandQueue(this, iconList);
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
-        boolean[] switches = new boolean[2];
+        boolean[] switches = new boolean[3];
         try {
             mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
                     switches);
@@ -75,6 +75,7 @@
 
         setLightsOn(switches[0]);
         setMenuKeyVisible(switches[1]);
+        setIMEButtonVisible(switches[2]);
 
         // Set up the initial icon state
         int N = iconList.size();
@@ -119,6 +120,7 @@
                    + " icons=" + iconList.size()
                    + " lights=" + (switches[0]?"on":"off")
                    + " menu=" + (switches[1]?"visible":"invisible")
+                   + " imeButton=" + (switches[2]?"visible":"invisible")
                    );
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
index ba682b7..c52bd4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
@@ -16,26 +16,44 @@
 
 package com.android.systemui.statusbar.tablet;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.provider.Settings;
+import android.util.Log;
 import android.util.Slog;
-import android.view.View;
 import android.util.AttributeSet;
-import android.widget.ImageView;
+import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+import android.view.View;
+import android.widget.ImageView;
 
 import com.android.server.InputMethodManagerService;
+import com.android.systemui.R;
+
+import java.util.Calendar;
+import java.util.List;
+import java.util.TimeZone;
 
 public class InputMethodButton extends ImageView {
 
+    private static final String  TAG = "StatusBar/InputMethodButton";
+
+    private boolean mKeyboardShown;
+    private ImageView mIcon;
     // other services we wish to talk to
-    InputMethodManager mImm;
+    private InputMethodManager mImm;
 
     public InputMethodButton(Context context, AttributeSet attrs) {
         super(context, attrs);
 
+        mKeyboardShown = false;
         // IME hookup
         mImm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-        
         // TODO: read the current icon & visibility state directly from the service
 
         // TODO: register for notifications about changes to visibility & subtype from service
@@ -47,5 +65,77 @@
             }
         });
     }
-}
 
+    @Override
+    protected void onAttachedToWindow() {
+        mIcon = (ImageView) findViewById(R.id.imeButton);
+
+        refreshStatusIcon(mKeyboardShown);
+    }
+
+    private InputMethodInfo getCurrentInputMethodInfo() {
+        String curInputMethodId = Settings.Secure.getString(getContext()
+                .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+        List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
+        if (curInputMethodId != null) {
+            for (InputMethodInfo imi: imis) {
+                if (imi.getId().equals(curInputMethodId)) {
+                    return imi;
+                }
+            }
+        }
+        return null;
+    }
+
+    private Drawable getCurrentSubtypeIcon() {
+        final PackageManager pm = getContext().getPackageManager();
+        InputMethodInfo imi = getCurrentInputMethodInfo();
+        InputMethodSubtype subtype = mImm.getCurrentInputMethodSubtype();
+        Drawable icon = null;
+        if (imi != null) {
+            if (subtype != null) {
+                return pm.getDrawable(imi.getPackageName(), subtype.getIconResId(),
+                        imi.getServiceInfo().applicationInfo);
+            } else if (imi.getSubtypes().size() > 0) {
+                return pm.getDrawable(imi.getPackageName(),
+                        imi.getSubtypes().get(0).getIconResId(),
+                        imi.getServiceInfo().applicationInfo);
+            } else {
+                try {
+                    return pm.getApplicationInfo(imi.getPackageName(), 0).loadIcon(pm);
+                } catch (PackageManager.NameNotFoundException e) {
+                    Log.w(TAG, "Current IME cann't be found: " + imi.getPackageName());
+                }
+            }
+        }
+        return null;
+    }
+
+    private void refreshStatusIcon(boolean keyboardShown) {
+        if (!keyboardShown) {
+            setVisibility(View.INVISIBLE);
+            return;
+        } else {
+            setVisibility(View.VISIBLE);
+        }
+        Drawable icon = getCurrentSubtypeIcon();
+        if (icon == null) {
+            mIcon.setImageResource(R.drawable.ic_sysbar_ime_default);
+        } else {
+            mIcon.setImageDrawable(icon);
+        }
+    }
+
+    private void postRefreshStatusIcon() {
+        getHandler().post(new Runnable() {
+            public void run() {
+                refreshStatusIcon(mKeyboardShown);
+            }
+        });
+    }
+
+    public void setIMEButtonVisible(boolean visible) {
+        mKeyboardShown = visible;
+        postRefreshStatusIcon();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
index 2b4f9d2..df29f95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
@@ -24,6 +24,7 @@
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.ImageView;
+import android.view.MotionEvent;
 
 import com.android.systemui.R;
 
@@ -43,12 +44,12 @@
         public IconLayout(Context context, AttributeSet attrs) {
             super(context, attrs);
         }
-    }
 
-    static class DraggerView extends View {
-        public DraggerView(Context context, AttributeSet attrs) {
-            super(context, attrs);
+        public boolean onInterceptTouchEvent(MotionEvent e) {
+            return true;
         }
     }
 }
 
+
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index 10b52f2..7ee3c19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -116,7 +116,7 @@
         mClipping = clipping;
         if (mClipping != null) {
             Bitmap icon = mClipping.getIcon();
-            mDescription.setText(mClipping.getLabel());
+            mDescription.setText(mClipping.getDescription().getLabel());
             if (icon != null) {
                 mPreviewIcon.setImageBitmap(icon);
                 mPreviewIcon.setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index fff70bc..9dc7850 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -18,7 +18,10 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 
+import android.animation.LayoutTransition;
+import android.animation.ObjectAnimator;
 import android.app.ActivityManagerNative;
 import android.app.PendingIntent;
 import android.app.Notification;
@@ -41,6 +44,7 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
@@ -65,6 +69,8 @@
 
     public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
     public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
+    public static final int MSG_OPEN_NOTIFICATION_PEEK = 1002;
+    public static final int MSG_CLOSE_NOTIFICATION_PEEK = 1003;
     public static final int MSG_OPEN_SYSTEM_PANEL = 1010;
     public static final int MSG_CLOSE_SYSTEM_PANEL = 1011;
     public static final int MSG_OPEN_RECENTS_PANEL = 1020;
@@ -89,8 +95,17 @@
     View mMenuButton;
     View mRecentButton;
 
+    InputMethodButton mInputMethodButton;
+
     NotificationPanel mNotificationPanel;
     SystemPanel mSystemPanel;
+    NotificationPanel mNotificationPeekWindow;
+    ViewGroup mNotificationPeekRow;
+    int mNotificationPeekIndex;
+    LayoutTransition mNotificationPeekScrubLeft, mNotificationPeekScrubRight;
+
+    int mNotificationPeekTapDuration;
+    int mNotificationFlingVelocity;
 
     ViewGroup mPile;
     TextView mClearButton;
@@ -132,7 +147,7 @@
         mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
 
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                400, // ViewGroup.LayoutParams.WRAP_CONTENT,
+                512, // ViewGroup.LayoutParams.WRAP_CONTENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
@@ -144,6 +159,41 @@
 
         WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
 
+        // Notification preview window
+        mNotificationPeekWindow = (NotificationPanel) View.inflate(context,
+                R.layout.sysbar_panel_notification_peek, null);
+        mNotificationPeekRow = (ViewGroup) mNotificationPeekWindow.findViewById(R.id.content);
+        mNotificationPeekWindow.setVisibility(View.GONE);
+        mNotificationPeekWindow.setOnTouchListener(
+                new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPeekWindow));
+        mNotificationPeekScrubRight = new LayoutTransition();
+        mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING, 
+                ObjectAnimator.ofInt(null, "left", -512, 0));
+        mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING, 
+                ObjectAnimator.ofInt(null, "left", -512, 0));
+        mNotificationPeekScrubRight.setDuration(500);
+
+        mNotificationPeekScrubLeft = new LayoutTransition();
+        mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING, 
+                ObjectAnimator.ofInt(null, "left", 512, 0));
+        mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING, 
+                ObjectAnimator.ofInt(null, "left", 512, 0));
+        mNotificationPeekScrubLeft.setDuration(500);
+
+        // XXX: setIgnoreChildren?
+        lp = new WindowManager.LayoutParams(
+                512, // ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                PixelFormat.TRANSLUCENT);
+        lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+        lp.setTitle("NotificationPeekWindow");
+        lp.windowAnimations = com.android.internal.R.style.Animation_Toast;
+
+        WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp);
+
         // System Panel
         mSystemPanel = (SystemPanel) View.inflate(context, R.layout.sysbar_panel_system, null);
         mSystemPanel.setVisibility(View.GONE);
@@ -238,9 +288,13 @@
         mDoNotDisturbButton = (TextView)mNotificationButtons.findViewById(R.id.do_not_disturb);
         mDoNotDisturbButton.setOnClickListener(mOnClickListener);
 
-
         // where the icons go
         mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
+        mIconLayout.setOnTouchListener(new NotificationIconTouchListener());
+
+        ViewConfiguration vc = ViewConfiguration.get(context);
+        mNotificationPeekTapDuration = vc.getTapTimeout();
+        mNotificationFlingVelocity = 300; // px/s
 
         mTicker = new TabletTicker(context, (FrameLayout)sb.findViewById(R.id.ticker));
 
@@ -253,6 +307,9 @@
         mNavigationArea = sb.findViewById(R.id.navigationArea);
         mMenuButton = mNavigationArea.findViewById(R.id.menu);
 
+        // The bar contents buttons
+        mInputMethodButton = (InputMethodButton) mBarContents.findViewById(R.id.imeButton);
+
         // set the initial view visibility
         setAreThereNotifications();
         refreshNotificationTrigger();
@@ -276,9 +333,57 @@
     private class H extends Handler {
         public void handleMessage(Message m) {
             switch (m.what) {
+                case MSG_OPEN_NOTIFICATION_PEEK:
+                    if (DEBUG) Slog.d(TAG, "opening notification peek window; arg=" + m.arg1);
+                    if (m.arg1 >= 0) {
+                        final int N = mNotns.size();
+                        if (mNotificationPeekIndex < N) {
+                            NotificationData.Entry entry = mNotns.get(N-1-mNotificationPeekIndex);
+                            entry.icon.setBackgroundColor(0);
+                        }
+
+                        final int peekIndex = m.arg1;
+                        if (peekIndex < N) {
+                            Slog.d(TAG, "loading peek: " + peekIndex);
+                            NotificationData.Entry entry = mNotns.get(N-1-peekIndex);
+                            NotificationData.Entry copy = new NotificationData.Entry(
+                                    entry.key, 
+                                    entry.notification, 
+                                    entry.icon);
+                            inflateViews(copy, mNotificationPeekRow);
+
+                            entry.icon.setBackgroundColor(0x20FFFFFF);
+
+//                          mNotificationPeekRow.setLayoutTransition(
+//                              peekIndex < mNotificationPeekIndex 
+//                                  ? mNotificationPeekScrubLeft
+//                                  : mNotificationPeekScrubRight);
+
+                            mNotificationPeekRow.removeAllViews();
+                            mNotificationPeekRow.addView(copy.row);
+
+                            mNotificationPeekWindow.setVisibility(View.VISIBLE);
+                            mNotificationPanel.setVisibility(View.GONE);
+
+                            mNotificationPeekIndex = peekIndex;
+                        }
+                    }
+                    break;
+                case MSG_CLOSE_NOTIFICATION_PEEK:
+                    if (DEBUG) Slog.d(TAG, "closing notification peek window");
+                    mNotificationPeekWindow.setVisibility(View.GONE);
+                    mNotificationPeekRow.removeAllViews();
+                    final int N = mNotns.size();
+                    if (mNotificationPeekIndex < N) {
+                        NotificationData.Entry entry = mNotns.get(N-1-mNotificationPeekIndex);
+                        entry.icon.setBackgroundColor(0);
+                    }
+                    break;
                 case MSG_OPEN_NOTIFICATION_PANEL:
                     if (DEBUG) Slog.d(TAG, "opening notifications panel");
                     if (mNotificationPanel.getVisibility() == View.GONE) {
+                        mNotificationPeekWindow.setVisibility(View.GONE);
+
                         mDoNotDisturbButton.setText(mNotificationsOn
                                 ? R.string.status_bar_do_not_disturb_button
                                 : R.string.status_bar_please_disturb_button);
@@ -308,6 +413,7 @@
                 case MSG_CLOSE_SYSTEM_PANEL:
                     if (DEBUG) Slog.d(TAG, "closing system panel");
                     mSystemPanel.setVisibility(View.GONE);
+                    break;
                 case MSG_OPEN_RECENTS_PANEL:
                     if (DEBUG) Slog.d(TAG, "opening recents panel");
                     if (mRecentsPanel != null) mRecentsPanel.setVisibility(View.VISIBLE);
@@ -335,7 +441,7 @@
         }
         mNotificationTrigger.setImageResource(resId);
     }
-    
+
     public void setBatteryMeter(int level, boolean plugged) {
         if (DEBUG) Slog.d(TAG, "battery=" + level + (plugged ? " - plugged" : " - unplugged"));
         mBatteryMeter.setImageResource(R.drawable.sysbar_batterymini);
@@ -589,6 +695,14 @@
                 visible ? R.anim.navigation_in : R.anim.navigation_out);
     }
 
+    public void setIMEButtonVisible(boolean visible) {
+
+        if (DEBUG) {
+            Slog.d(TAG, (visible?"showing":"hiding") + " the IME button");
+        }
+        mInputMethodButton.setIMEButtonVisible(visible);
+    }
+
     private void setAreThereNotifications() {
         final boolean hasClearable = mNotns.hasClearableItems();
 
@@ -811,6 +925,72 @@
         return entry.notification;
     }
 
+    private class NotificationIconTouchListener implements View.OnTouchListener {
+        VelocityTracker mVT;
+
+        public NotificationIconTouchListener() {
+        }
+
+        public boolean onTouch(View v, MotionEvent event) {
+            boolean peeking = mNotificationPeekWindow.getVisibility() != View.GONE;
+            boolean panelShowing = mNotificationPanel.getVisibility() != View.GONE;
+            if (panelShowing) return false;
+
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_DOWN:
+                    mVT = VelocityTracker.obtain();
+
+                    // fall through
+                case MotionEvent.ACTION_OUTSIDE:
+                case MotionEvent.ACTION_MOVE:
+                    // peek and switch icons if necessary
+                    int numIcons = mIconLayout.getChildCount();
+                    int peekIndex = 
+                            (int)((float)event.getX() * numIcons / mIconLayout.getWidth());
+                    if (peekIndex > numIcons - 1) peekIndex = numIcons - 1;
+                    else if (peekIndex < 0) peekIndex = 0;
+
+                    if (!peeking || mNotificationPeekIndex != peekIndex) {
+                        if (DEBUG) Slog.d(TAG, "will peek at notification #" + peekIndex);
+                        Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
+                        peekMsg.arg1 = peekIndex;
+
+                        mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
+
+                        // no delay if we're scrubbing left-right
+                        mHandler.sendMessageDelayed(peekMsg,
+                                peeking ? 0 : mNotificationPeekTapDuration);
+                    }
+
+                    // check for fling
+                    if (mVT != null) {
+                        mVT.addMovement(event);
+                        mVT.computeCurrentVelocity(1000);
+                        // require a little more oomph once we're already in peekaboo mode
+                        if (!panelShowing && (
+                               (peeking && mVT.getYVelocity() < -mNotificationFlingVelocity*3)
+                            || (mVT.getYVelocity() < -mNotificationFlingVelocity))) {
+                            mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
+                            mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
+                            mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
+                            mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
+                        }
+                    }
+                    return true;
+                case MotionEvent.ACTION_UP:
+                case MotionEvent.ACTION_CANCEL:
+                    mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
+                    if (peeking) {
+                        mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK, 250);
+                    }
+                    mVT.recycle();
+                    mVT = null;
+                    return true;
+            }
+            return false;
+        }
+    }
+
     StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
         if (DEBUG) {
             Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
@@ -835,6 +1015,7 @@
                     + notification);
             return null;
         }
+
         // Add the icon.
         mNotns.add(entry);
         refreshIcons();
@@ -846,28 +1027,76 @@
         // XXX: need to implement a new limited linear layout class
         // to avoid removing & readding everything
 
+        final int ICON_LIMIT = 4;
+        final LinearLayout.LayoutParams params
+            = new LinearLayout.LayoutParams(mIconSize, mIconSize);
+
         int N = mNotns.size();
-        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mIconSize, mIconSize);
 
         if (DEBUG) {
-            Slog.d(TAG, "refreshing icons (" + N + " notifications, mIconLayout="
-                    + mIconLayout + ", mPile=" + mPile);
+            Slog.d(TAG, "refreshing icons: " + N + " notifications, mIconLayout=" + mIconLayout);
         }
 
-        mIconLayout.removeAllViews();
-        for (int i=0; i<4; i++) {
+        ArrayList<View> toShow = new ArrayList<View>();
+
+        for (int i=0; i<ICON_LIMIT; i++) {
             if (i>=N) break;
-            mIconLayout.addView(mNotns.get(N-i-1).icon, i, params);
+            toShow.add(mNotns.get(N-i-1).icon);
         }
 
-        mPile.removeAllViews();
-        for (int i=0; i<N; i++) {
-            mPile.addView(mNotns.get(N-i-1).row);
+        ArrayList<View> toRemove = new ArrayList<View>();
+        for (int i=0; i<mIconLayout.getChildCount(); i++) {
+            View child = mIconLayout.getChildAt(i);
+            if (!toShow.contains(child)) {
+                toRemove.add(child);
+            }
         }
 
+        for (View remove : toRemove) {
+            mIconLayout.removeView(remove);
+        }
+
+        for (int i=0; i<toShow.size(); i++) {
+            View v = toShow.get(i);
+            if (v.getParent() == null) {
+                mIconLayout.addView(toShow.get(i), i, params);
+            }
+        }
+
+        loadNotificationPanel();
         refreshNotificationTrigger();
     }
 
+    private void loadNotificationPanel() {
+        int N = mNotns.size();
+
+        ArrayList<View> toShow = new ArrayList<View>();
+
+        for (int i=0; i<N; i++) {
+            View row = mNotns.get(N-i-1).row;
+            toShow.add(row);
+        }
+
+        ArrayList<View> toRemove = new ArrayList<View>();
+        for (int i=0; i<mPile.getChildCount(); i++) {
+            View child = mPile.getChildAt(i);
+            if (!toShow.contains(child)) {
+                toRemove.add(child);
+            }
+        }
+
+        for (View remove : toRemove) {
+            mPile.removeView(remove);
+        }
+
+        for (int i=0; i<toShow.size(); i++) {
+            View v = toShow.get(i);
+            if (v.getParent() == null) {
+                mPile.addView(toShow.get(i));
+            }
+        }
+    }
+
     private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
         StatusBarNotification sbn = entry.notification;
         RemoteViews remoteViews = sbn.notification.contentView;
diff --git a/packages/VpnServices/res/values-fr/strings.xml b/packages/VpnServices/res/values-fr/strings.xml
index 80fefa4..4a93e0a 100644
--- a/packages/VpnServices/res/values-fr/strings.xml
+++ b/packages/VpnServices/res/values-fr/strings.xml
@@ -2,7 +2,7 @@
 <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">"Services VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN \n<xliff:g id="PROFILENAME">%s</xliff:g> connecté"</string>
+    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> connecté"</string>
     <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> déconnecté"</string>
     <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Touchez l\'écran pour vous reconnecter à un VPN."</string>
 </resources>
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b4c696b..cd1ad4c 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -256,8 +256,10 @@
         }
     };
     
-    // The current size of the screen.
-    int mW, mH;
+    // The current size of the screen; these may be different than (0,0)-(dw,dh)
+    // if the status bar can't be hidden; in that case it effectively carves out
+    // that area of the display from all other windows.
+    int mScreenLeft, mScreenTop, mScreenWidth, mScreenHeight;
     // During layout, the current screen borders with all outer decoration
     // (status bar, input method dock) accounted for.
     int mCurLeft, mCurTop, mCurRight, mCurBottom;
@@ -1316,10 +1318,11 @@
     public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
         final int fl = attrs.flags;
         
-        if (mStatusBarCanHide && (fl &
-                (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
+        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
                 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
-            contentInset.set(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom);
+            contentInset.set(mCurLeft, mCurTop,
+                    (mScreenLeft+mScreenWidth) - mCurRight,
+                    (mScreenTop+mScreenHeight) - mCurBottom);
         } else {
             contentInset.setEmpty();
         }
@@ -1327,8 +1330,9 @@
     
     /** {@inheritDoc} */
     public void beginLayoutLw(int displayWidth, int displayHeight) {
-        mW = displayWidth;
-        mH = displayHeight;
+        mScreenLeft = mScreenTop = 0;
+        mScreenWidth = displayWidth;
+        mScreenHeight = displayHeight;
         mDockLeft = mContentLeft = mCurLeft = 0;
         mDockTop = mContentTop = mCurTop = 0;
         mDockRight = mContentRight = mCurRight = displayWidth;
@@ -1350,16 +1354,34 @@
                 // If the status bar is hidden, we don't want to cause
                 // windows behind it to scroll.
                 final Rect r = mStatusBar.getFrameLw();
-                if (mDockTop == r.top) mDockTop = r.bottom;
-                else if (mDockBottom == r.bottom) mDockBottom = r.top;
-                mContentTop = mCurTop = mDockTop;
-                mContentBottom = mCurBottom = mDockBottom;
-                if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockTop=" + mDockTop
-                        + " mContentTop=" + mContentTop
-                        + " mCurTop=" + mCurTop
-                        + " mDockBottom=" + mDockBottom
-                        + " mContentBottom=" + mContentBottom
-                        + " mCurBottom=" + mCurBottom);
+                if (mStatusBarCanHide) {
+                    // Status bar may go away, so the screen area it occupies
+                    // is available to apps but just covering them when the
+                    // status bar is visible.
+                    if (mDockTop == r.top) mDockTop = r.bottom;
+                    else if (mDockBottom == r.bottom) mDockBottom = r.top;
+                    mContentTop = mCurTop = mDockTop;
+                    mContentBottom = mCurBottom = mDockBottom;
+                    if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockTop=" + mDockTop
+                            + " mContentTop=" + mContentTop
+                            + " mCurTop=" + mCurTop
+                            + " mDockBottom=" + mDockBottom
+                            + " mContentBottom=" + mContentBottom
+                            + " mCurBottom=" + mCurBottom);
+                } else {
+                    // Status bar can't go away; the part of the screen it
+                    // covers does not exist for anything behind it.
+                    if (mScreenTop == r.top) {
+                        mScreenTop = r.bottom;
+                        mScreenHeight -= (r.bottom-r.top);
+                    } else if ((mScreenHeight-mScreenTop) == r.bottom) {
+                        mScreenHeight -= (r.bottom-r.top);
+                    }
+                    mContentTop = mCurTop = mDockTop = mScreenTop;
+                    mContentBottom = mCurBottom = mDockBottom = mScreenTop+mScreenHeight;
+                    if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mScreenTop=" + mScreenTop
+                            + " mScreenHeight=" + mScreenHeight);
+                }
             }
         }
     }
@@ -1444,8 +1466,7 @@
             attrs.gravity = Gravity.BOTTOM;
             mDockLayer = win.getSurfaceLayer();
         } else {
-            if (mStatusBarCanHide && (fl &
-                    (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
+            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
                     == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
                 // This is the case for a normal activity window: we want it
                 // to cover all of the screen space, and it can take care of
@@ -1456,10 +1477,10 @@
                     // frame is the same as the one we are attached to.
                     setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
                 } else {
-                    pf.left = df.left = 0;
-                    pf.top = df.top = 0;
-                    pf.right = df.right = mW;
-                    pf.bottom = df.bottom = mH;
+                    pf.left = df.left = mScreenLeft;
+                    pf.top = df.top = mScreenTop;
+                    pf.right = df.right = mScreenLeft+mScreenWidth;
+                    pf.bottom = df.bottom = mScreenTop+mScreenHeight;
                     if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
                         cf.left = mDockLeft;
                         cf.top = mDockTop;
@@ -1476,13 +1497,13 @@
                     vf.right = mCurRight;
                     vf.bottom = mCurBottom;
                 }
-            } else if (mStatusBarCanHide && (fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
+            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
                 // A window that has requested to fill the entire screen just
                 // gets everything, period.
-                pf.left = df.left = cf.left = 0;
-                pf.top = df.top = cf.top = 0;
-                pf.right = df.right = cf.right = mW;
-                pf.bottom = df.bottom = cf.bottom = mH;
+                pf.left = df.left = cf.left = mScreenLeft;
+                pf.top = df.top = cf.top = mScreenTop;
+                pf.right = df.right = cf.right = mScreenLeft+mScreenWidth;
+                pf.bottom = df.bottom = cf.bottom = mScreenTop+mScreenHeight;
                 vf.left = mCurLeft;
                 vf.top = mCurTop;
                 vf.right = mCurRight;
@@ -1743,9 +1764,9 @@
                     rect.union(w.getShownFrameLw());
                 }
             }
-            final int insetw = mW/10;
-            final int inseth = mH/10;
-            if (rect.contains(insetw, inseth, mW-insetw, mH-inseth)) {
+            final int insetw = mScreenWidth/10;
+            final int inseth = mScreenHeight/10;
+            if (rect.contains(insetw, inseth, mScreenWidth-insetw, mScreenHeight-inseth)) {
                 // All of the status bar windows put together cover the
                 // screen, so the app can't be seen.  (Note this test doesn't
                 // work if the rects of these windows are at off offsets or
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 32dd0d5..40883bd 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -43,6 +43,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.Arrays;
 
 
 /**
@@ -76,7 +77,7 @@
 
     // Used locally for determining when to make a last ditch effort to log
     // discharge stats before the device dies.
-    private static final int CRITICAL_BATTERY_LEVEL = 4;
+    private int mCriticalBatteryLevel;
 
     private static final int DUMP_MAX_LENGTH = 24 * 1024;
     private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "-u" };
@@ -100,7 +101,7 @@
     private int mBatteryTemperature;
     private String mBatteryTechnology;
     private boolean mBatteryLevelCritical;
-    private boolean mInvalidCharger;
+    private int mInvalidCharger;
 
     private int mLastBatteryStatus;
     private int mLastBatteryHealth;
@@ -109,7 +110,7 @@
     private int mLastBatteryVoltage;
     private int mLastBatteryTemperature;
     private boolean mLastBatteryLevelCritical;
-    private boolean mLastInvalidCharger;
+    private int mLastInvalidCharger;
 
     private int mLowBatteryWarningLevel;
     private int mLowBatteryCloseWarningLevel;
@@ -120,12 +121,17 @@
     private long mDischargeStartTime;
     private int mDischargeStartLevel;
 
+    private Led mLed;
+
     private boolean mSentLowBatteryBroadcast = false;
 
-    public BatteryService(Context context) {
+    public BatteryService(Context context, LightsService lights) {
         mContext = context;
+        mLed = new Led(context, lights);
         mBatteryStats = BatteryStatsService.getService();
 
+        mCriticalBatteryLevel = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_criticalBatteryWarningLevel);
         mLowBatteryWarningLevel = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lowBatteryWarningLevel);
         mLowBatteryCloseWarningLevel = mContext.getResources().getInteger(
@@ -180,7 +186,7 @@
     private UEventObserver mInvalidChargerObserver = new UEventObserver() {
         @Override
         public void onUEvent(UEventObserver.UEvent event) {
-            boolean invalidCharger = "1".equals(event.get("SWITCH_STATE"));
+            int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
             if (mInvalidCharger != invalidCharger) {
                 mInvalidCharger = invalidCharger;
                 update();
@@ -225,11 +231,14 @@
 
     private synchronized final void update() {
         native_update();
+        processValues();
+    }
 
+    private void processValues() {
         boolean logOutlier = false;
         long dischargeDuration = 0;
 
-        mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL;
+        mBatteryLevelCritical = mBatteryLevel <= mCriticalBatteryLevel;
         if (mAcOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
         } else if (mUsbOnline) {
@@ -311,9 +320,9 @@
              *   (becomes <= mLowBatteryWarningLevel).
              */
             final boolean sendBatteryLow = !plugged
-                && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
-                && mBatteryLevel <= mLowBatteryWarningLevel
-                && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);
+                    && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
+                    && mBatteryLevel <= mLowBatteryWarningLevel
+                    && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);
 
             sendIntent();
 
@@ -341,6 +350,9 @@
                 mContext.sendBroadcast(statusIntent);
             }
 
+            // Update the battery LED
+            mLed.updateLightsLocked();
+
             // This needs to be done after sendIntent() so that we get the lastest battery stats.
             if (logOutlier && dischargeDuration != 0) {
                 logOutlier(dischargeDuration);
@@ -378,8 +390,8 @@
         intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology);
         intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
 
-        if (false) {
-            Slog.d(TAG, "updateBattery level:" + mBatteryLevel +
+        if (true) {
+            Slog.d(TAG, "level:" + mBatteryLevel +
                     " scale:" + BATTERY_SCALE + " status:" + mBatteryStatus +
                     " health:" + mBatteryHealth +  " present:" + mBatteryPresent +
                     " voltage: " + mBatteryVoltage +
@@ -481,18 +493,109 @@
             return;
         }
 
-        synchronized (this) {
-            pw.println("Current Battery Service state:");
-            pw.println("  AC powered: " + mAcOnline);
-            pw.println("  USB powered: " + mUsbOnline);
-            pw.println("  status: " + mBatteryStatus);
-            pw.println("  health: " + mBatteryHealth);
-            pw.println("  present: " + mBatteryPresent);
-            pw.println("  level: " + mBatteryLevel);
-            pw.println("  scale: " + BATTERY_SCALE);
-            pw.println("  voltage:" + mBatteryVoltage);
-            pw.println("  temperature: " + mBatteryTemperature);
-            pw.println("  technology: " + mBatteryTechnology);
+        if (args == null || args.length == 0) {
+            synchronized (this) {
+                pw.println("Current Battery Service state:");
+                pw.println("  AC powered: " + mAcOnline);
+                pw.println("  USB powered: " + mUsbOnline);
+                pw.println("  status: " + mBatteryStatus);
+                pw.println("  health: " + mBatteryHealth);
+                pw.println("  present: " + mBatteryPresent);
+                pw.println("  level: " + mBatteryLevel);
+                pw.println("  scale: " + BATTERY_SCALE);
+                pw.println("  voltage:" + mBatteryVoltage);
+                pw.println("  temperature: " + mBatteryTemperature);
+                pw.println("  technology: " + mBatteryTechnology);
+            }
+        } else if (false) {
+            // DO NOT SUBMIT WITH THIS TURNED ON
+            if (args.length == 3 && "set".equals(args[0])) {
+                String key = args[1];
+                String value = args[2];
+                try {
+                    boolean update = true;
+                    if ("ac".equals(key)) {
+                        mAcOnline = Integer.parseInt(value) != 0;
+                    } else if ("usb".equals(key)) {
+                        mUsbOnline = Integer.parseInt(value) != 0;
+                    } else if ("status".equals(key)) {
+                        mBatteryStatus = Integer.parseInt(value);
+                    } else if ("level".equals(key)) {
+                        mBatteryLevel = Integer.parseInt(value);
+                    } else if ("invalid".equals(key)) {
+                        mInvalidCharger = Integer.parseInt(value);
+                    } else {
+                        update = false;
+                    }
+                    if (update) {
+                        processValues();
+                    }
+                } catch (NumberFormatException ex) {
+                    pw.println("Bad value: " + value);
+                }
+            }
+        }
+    }
+
+    class Led {
+        private LightsService mLightsService;
+        private LightsService.Light mBatteryLight;
+
+        private int mBatteryLowARGB;
+        private int mBatteryMediumARGB;
+        private int mBatteryFullARGB;
+        private int mBatteryLedOn;
+        private int mBatteryLedOff;
+
+        private boolean mBatteryCharging;
+        private boolean mBatteryLow;
+        private boolean mBatteryFull;
+
+        Led(Context context, LightsService lights) {
+            mLightsService = lights;
+            mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY);
+
+            mBatteryLowARGB = mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_notificationsBatteryLowARGB);
+            mBatteryMediumARGB = mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_notificationsBatteryMediumARGB);
+            mBatteryFullARGB = mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_notificationsBatteryFullARGB);
+            mBatteryLedOn = mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_notificationsBatteryLedOn);
+            mBatteryLedOff = mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_notificationsBatteryLedOff);
+        }
+
+        /**
+         * Synchronize on BatteryService.
+         */
+        void updateLightsLocked() {
+            final int level = mBatteryLevel;
+            final int status = mBatteryStatus;
+            if (level < mLowBatteryWarningLevel) {
+                if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
+                    // Solid red when battery is charging
+                    mBatteryLight.setColor(mBatteryLowARGB);
+                } else {
+                    // Flash red when battery is low and not charging
+                    mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED,
+                            mBatteryLedOn, mBatteryLedOff);
+                }
+            } else if (status == BatteryManager.BATTERY_STATUS_CHARGING
+                    || status == BatteryManager.BATTERY_STATUS_FULL) {
+                if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {
+                    // Solid green when full or charging and nearly full
+                    mBatteryLight.setColor(mBatteryFullARGB);
+                } else {
+                    // Solid orange when charging and halfway full
+                    mBatteryLight.setColor(mBatteryMediumARGB);
+                }
+            } else {
+                // No lights if not charging and not low
+                mBatteryLight.turnOff();
+            }
         }
     }
 }
+
diff --git a/services/java/com/android/server/ClipboardService.java b/services/java/com/android/server/ClipboardService.java
index bdf313c..30ea48c 100644
--- a/services/java/com/android/server/ClipboardService.java
+++ b/services/java/com/android/server/ClipboardService.java
@@ -115,7 +115,7 @@
 
     public ClipDescription getPrimaryClipDescription() {
         synchronized (this) {
-            return new ClipDescription(mPrimaryClip);
+            return mPrimaryClip.getDescription();
         }
     }
 
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 70bde01..07da0fa 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -25,7 +25,6 @@
 import com.android.internal.view.IInputMethodManager;
 import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.InputBindResult;
-import com.android.internal.view.InputMethodAndSubtypeEnabler;
 
 import com.android.server.StatusBarManagerService;
 
@@ -941,6 +940,23 @@
         }
     }
 
+    public void setIMEButtonVisible(IBinder token, boolean visible) {
+        int uid = Binder.getCallingUid();
+        long ident = Binder.clearCallingIdentity();
+        try {
+            if (token == null || mCurToken != token) {
+                Slog.w(TAG, "Ignoring setIMEButtonVisible of uid " + uid + " token: " + token);
+                return;
+            }
+
+            synchronized (mMethodMap) {
+                mStatusBar.setIMEButtonVisible(visible);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     void updateFromSettingsLocked() {
         // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
         // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
@@ -1549,10 +1565,10 @@
     }
 
     private void showInputMethodAndSubtypeEnabler() {
-        Intent intent = new Intent();
-        intent.setClassName("android", InputMethodAndSubtypeEnabler.class.getCanonicalName());
+        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_AND_SUBTYPE_ENABLER);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
         mContext.startActivity(intent);
     }
 
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 8066fa7..1081a20 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -93,7 +93,6 @@
     private WorkerHandler mHandler;
     private StatusBarManagerService mStatusBar;
     private LightsService mLightsService;
-    private LightsService.Light mBatteryLight;
     private LightsService.Light mNotificationLight;
     private LightsService.Light mAttentionLight;
 
@@ -128,18 +127,8 @@
     private ArrayList<ToastRecord> mToastQueue;
 
     private ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>();
-
-    private boolean mBatteryCharging;
-    private boolean mBatteryLow;
-    private boolean mBatteryFull;
     private NotificationRecord mLedNotification;
 
-    private static int mBatteryLowARGB;
-    private static int mBatteryMediumARGB;
-    private static int mBatteryFullARGB;
-    private static int mBatteryLedOn;
-    private static int mBatteryLedOff;
-
     private static String idDebugString(Context baseContext, String packageName, int id) {
         Context c = null;
 
@@ -342,22 +331,7 @@
 
             boolean queryRestart = false;
             
-            if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
-                boolean batteryCharging = (intent.getIntExtra("plugged", 0) != 0);
-                int level = intent.getIntExtra("level", -1);
-                boolean batteryLow = (level >= 0 && level <= Power.LOW_BATTERY_THRESHOLD);
-                int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
-                boolean batteryFull = (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90);
-
-                if (batteryCharging != mBatteryCharging ||
-                        batteryLow != mBatteryLow ||
-                        batteryFull != mBatteryFull) {
-                    mBatteryCharging = batteryCharging;
-                    mBatteryLow = batteryLow;
-                    mBatteryFull = batteryFull;
-                    updateLights();
-                }
-            } else if (action.equals(Usb.ACTION_USB_STATE)) {
+            if (action.equals(Usb.ACTION_USB_STATE)) {
                 Bundle extras = intent.getExtras();
                 boolean usbConnected = extras.getBoolean(Usb.USB_CONNECTED);
                 boolean adbEnabled = (Usb.USB_FUNCTION_ENABLED.equals(
@@ -435,7 +409,6 @@
     {
         super();
         mContext = context;
-        mLightsService = lights;
         mAm = ActivityManagerNative.getDefault();
         mSound = new NotificationPlayer(TAG);
         mSound.setUsesWakeLock(context);
@@ -445,7 +418,6 @@
         mStatusBar = statusBar;
         statusBar.setNotificationCallbacks(mNotificationCallbacks);
 
-        mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY);
         mNotificationLight = lights.getLight(LightsService.LIGHT_ID_NOTIFICATIONS);
         mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);
 
@@ -457,17 +429,6 @@
         mDefaultNotificationLedOff = resources.getInteger(
                 com.android.internal.R.integer.config_defaultNotificationLedOff);
 
-        mBatteryLowARGB = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_notificationsBatteryLowARGB);
-        mBatteryMediumARGB = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_notificationsBatteryMediumARGB);
-        mBatteryFullARGB = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_notificationsBatteryFullARGB);
-        mBatteryLedOn = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_notificationsBatteryLedOn);
-        mBatteryLedOff = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_notificationsBatteryLedOff);
-
         // Don't start allowing notifications until the setup wizard has run once.
         // After that, including subsequent boots, init with notifications turned on.
         // This works on the first boot because the setup wizard will toggle this
@@ -479,7 +440,6 @@
 
         // register for battery changed notifications
         IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
         filter.addAction(Usb.ACTION_USB_STATE);
         filter.addAction(Intent.ACTION_SCREEN_ON);
         filter.addAction(Intent.ACTION_SCREEN_OFF);
@@ -1076,25 +1036,6 @@
     // lock on mNotificationList
     private void updateLightsLocked()
     {
-        // Battery low always shows, other states only show if charging.
-        if (mBatteryLow) {
-            if (mBatteryCharging) {
-                mBatteryLight.setColor(mBatteryLowARGB);
-            } else {
-                // Flash when battery is low and not charging
-                mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED,
-                        mBatteryLedOn, mBatteryLedOff);
-            }
-        } else if (mBatteryCharging) {
-            if (mBatteryFull) {
-                mBatteryLight.setColor(mBatteryFullARGB);
-            } else {
-                mBatteryLight.setColor(mBatteryMediumARGB);
-            }
-        } else {
-            mBatteryLight.turnOff();
-        }
-
         // clear pending pulse notification if screen is on
         if (mScreenOn || mLedNotification == null) {
             mPendingPulseNotification = false;
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 30e90a8..5cf013f 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -219,6 +219,8 @@
     private float mLightSensorValue = -1;
     private boolean mProxIgnoredBecauseScreenTurnedOff = false;
     private int mHighestLightSensorValue = -1;
+    private boolean mLightSensorPendingDecrease = false;
+    private boolean mLightSensorPendingIncrease = false;
     private float mLightSensorPendingValue = -1;
     private int mLightSensorScreenBrightness = -1;
     private int mLightSensorButtonBrightness = -1;
@@ -1141,6 +1143,8 @@
             pw.println("  mLightSensorEnabled=" + mLightSensorEnabled);
             pw.println("  mLightSensorValue=" + mLightSensorValue
                     + " mLightSensorPendingValue=" + mLightSensorPendingValue);
+            pw.println("  mLightSensorPendingDecrease=" + mLightSensorPendingDecrease
+                    + " mLightSensorPendingIncrease=" + mLightSensorPendingIncrease);
             pw.println("  mLightSensorScreenBrightness=" + mLightSensorScreenBrightness
                     + " mLightSensorButtonBrightness=" + mLightSensorButtonBrightness
                     + " mLightSensorKeyboardBrightness=" + mLightSensorKeyboardBrightness);
@@ -1742,6 +1746,8 @@
                 } else {
                     // cancel light sensor task
                     mHandler.removeCallbacks(mAutoBrightnessTask);
+                    mLightSensorPendingDecrease = false;
+                    mLightSensorPendingIncrease = false;
                     mScreenOffTime = SystemClock.elapsedRealtime();
                     long identity = Binder.clearCallingIdentity();
                     try {
@@ -2325,9 +2331,10 @@
     private Runnable mAutoBrightnessTask = new Runnable() {
         public void run() {
             synchronized (mLocks) {
-                int value = (int)mLightSensorPendingValue;
-                if (value >= 0) {
-                    mLightSensorPendingValue = -1;
+                if (mLightSensorPendingDecrease || mLightSensorPendingIncrease) {
+                    int value = (int)mLightSensorPendingValue;
+                    mLightSensorPendingDecrease = false;
+                    mLightSensorPendingIncrease = false;
                     lightSensorChangedLocked(value);
                 }
             }
@@ -2981,19 +2988,29 @@
                 if (mDebugLightSensor) {
                     Slog.d(TAG, "onSensorChanged: light value: " + value);
                 }
-                mHandler.removeCallbacks(mAutoBrightnessTask);
-                if (mLightSensorValue != value) {
-                    if (mLightSensorValue == -1 ||
-                            milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) {
-                        // process the value immediately if screen has just turned on
-                        lightSensorChangedLocked(value);
-                    } else {
-                        // delay processing to debounce the sensor
-                        mLightSensorPendingValue = value;
-                        mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
-                    }
+                if (mLightSensorValue == -1 ||
+                        milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) {
+                    // process the value immediately if screen has just turned on
+                    mHandler.removeCallbacks(mAutoBrightnessTask);
+                    mLightSensorPendingDecrease = false;
+                    mLightSensorPendingIncrease = false;
+                    lightSensorChangedLocked(value);
                 } else {
-                    mLightSensorPendingValue = -1;
+                    if ((value > mLightSensorValue && mLightSensorPendingDecrease) ||
+                            (value < mLightSensorValue && mLightSensorPendingIncrease) ||
+                            (value == mLightSensorValue) ||
+                            (!mLightSensorPendingDecrease && !mLightSensorPendingIncrease)) {
+                        // delay processing to debounce the sensor
+                        mHandler.removeCallbacks(mAutoBrightnessTask);
+                        mLightSensorPendingDecrease = (value < mLightSensorValue);
+                        mLightSensorPendingIncrease = (value > mLightSensorValue);
+                        if (mLightSensorPendingDecrease || mLightSensorPendingIncrease) {
+                            mLightSensorPendingValue = value;
+                            mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
+                        }
+                    } else {
+                        mLightSensorPendingValue = value;
+                    }
                 }
             }
         }
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 400b31f..95d2b65 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -74,6 +74,8 @@
 
     boolean mMenuVisible = false;
 
+    boolean mIMEButtonVisible = false;
+
     private class DisableRecord implements IBinder.DeathRecipient {
         String pkg;
         int what;
@@ -257,6 +259,28 @@
         }
     }
 
+    public void setIMEButtonVisible(final boolean visible) {
+        enforceStatusBar();
+
+        if (SPEW) Slog.d(TAG, (visible?"showing":"hiding") + " IME Button");
+
+        synchronized(mLock) {
+            if (mIMEButtonVisible != visible) {
+                mIMEButtonVisible = visible;
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        if (mBar != null) {
+                            try {
+                                mBar.setIMEButtonVisible(visible);
+                            } catch (RemoteException ex) {
+                            }
+                        }
+                    }
+                });
+            }
+        }
+    }
+
     /**
      * This is used for the automatic version of lights-out mode.  Only call this from
      * the window manager.
@@ -345,6 +369,7 @@
         synchronized (mLock) {
             switches[0] = mLightsOn;
             switches[1] = mMenuVisible;
+            switches[2] = mIMEButtonVisible;
         }
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 46797c5..237ab80 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -170,13 +170,13 @@
             Slog.i(TAG, "System Content Providers");
             ActivityManagerService.installSystemProviders();
 
-            Slog.i(TAG, "Battery Service");
-            battery = new BatteryService(context);
-            ServiceManager.addService("battery", battery);
-
             Slog.i(TAG, "Lights Service");
             lights = new LightsService(context);
 
+            Slog.i(TAG, "Battery Service");
+            battery = new BatteryService(context, lights);
+            ServiceManager.addService("battery", battery);
+
             Slog.i(TAG, "Vibrator Service");
             ServiceManager.addService("vibrator", new VibratorService(context));
 
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 92588fc..2008215 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -102,6 +102,8 @@
 
     private final LockList mLocks = new LockList();
     // some wifi lock statistics
+    private int mFullHighPerfLocksAcquired;
+    private int mFullHighPerfLocksReleased;
     private int mFullLocksAcquired;
     private int mFullLocksReleased;
     private int mScanLocksAcquired;
@@ -366,7 +368,7 @@
                             /* IP/netmask: 192.168.43.1/255.255.255.0 */
                             ifcg.ipAddr = (192 << 24) + (168 << 16) + (43 << 8) + 1;
                             ifcg.netmask = (255 << 24) + (255 << 16) + (255 << 8) + 0;
-                            ifcg.interfaceFlags = "up";
+                            ifcg.interfaceFlags = "[up]";
 
                             service.setInterfaceConfig(intf, ifcg);
                         }
@@ -1040,12 +1042,15 @@
         boolean wifiEnabled = getPersistedWifiEnabled();
         boolean airplaneMode = isAirplaneModeOn() && !mAirplaneModeOverwridden.get();
         boolean lockHeld = mLocks.hasLocks();
-        int strongestLockMode;
+        int strongestLockMode = WifiManager.WIFI_MODE_FULL;
         boolean wifiShouldBeEnabled = wifiEnabled && !airplaneMode;
         boolean wifiShouldBeStarted = !mDeviceIdle || lockHeld;
-        if (mDeviceIdle && lockHeld) {
+
+        if (lockHeld) {
             strongestLockMode = mLocks.getStrongestLockMode();
-        } else {
+        }
+        /* If device is not idle, lockmode cannot be scan only */
+        if (!mDeviceIdle && strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY) {
             strongestLockMode = WifiManager.WIFI_MODE_FULL;
         }
 
@@ -1067,6 +1072,8 @@
                 mWifiStateMachine.setDriverStart(true);
                 mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
                         System.currentTimeMillis() + scanMs, scanMs, mScanIntent);
+                mWifiStateMachine.setHighPerfModeEnabled(strongestLockMode
+                        == WifiManager.WIFI_MODE_FULL_HIGH_PERF);
             } else {
                 mWifiStateMachine.requestCmWakeLock();
                 mWifiStateMachine.setDriverStart(false);
@@ -1145,8 +1152,10 @@
         }
         pw.println();
         pw.println("Locks acquired: " + mFullLocksAcquired + " full, " +
+                mFullHighPerfLocksAcquired + " full high perf, " +
                 mScanLocksAcquired + " scan");
         pw.println("Locks released: " + mFullLocksReleased + " full, " +
+                mFullHighPerfLocksReleased + " full high perf, " +
                 mScanLocksReleased + " scan");
         pw.println();
         pw.println("Locks held:");
@@ -1184,11 +1193,15 @@
             if (mList.isEmpty()) {
                 return WifiManager.WIFI_MODE_FULL;
             }
-            for (WifiLock l : mList) {
-                if (l.mMode == WifiManager.WIFI_MODE_FULL) {
-                    return WifiManager.WIFI_MODE_FULL;
-                }
+
+            if (mFullHighPerfLocksAcquired > mFullHighPerfLocksReleased) {
+                return WifiManager.WIFI_MODE_FULL_HIGH_PERF;
             }
+
+            if (mFullLocksAcquired > mFullLocksReleased) {
+                return WifiManager.WIFI_MODE_FULL;
+            }
+
             return WifiManager.WIFI_MODE_SCAN_ONLY;
         }
 
@@ -1235,7 +1248,11 @@
 
     public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
-        if (lockMode != WifiManager.WIFI_MODE_FULL && lockMode != WifiManager.WIFI_MODE_SCAN_ONLY) {
+        if (lockMode != WifiManager.WIFI_MODE_FULL &&
+                lockMode != WifiManager.WIFI_MODE_SCAN_ONLY &&
+                lockMode != WifiManager.WIFI_MODE_FULL_HIGH_PERF) {
+            Slog.e(TAG, "Illegal argument, lockMode= " + lockMode);
+            if (DBG) throw new IllegalArgumentException("lockMode=" + lockMode);
             return false;
         }
         if (ws != null && ws.size() == 0) {
@@ -1256,6 +1273,7 @@
     private void noteAcquireWifiLock(WifiLock wifiLock) throws RemoteException {
         switch(wifiLock.mMode) {
             case WifiManager.WIFI_MODE_FULL:
+            case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
                 mBatteryStats.noteFullWifiLockAcquiredFromSource(wifiLock.mWorkSource);
                 break;
             case WifiManager.WIFI_MODE_SCAN_ONLY:
@@ -1267,6 +1285,7 @@
     private void noteReleaseWifiLock(WifiLock wifiLock) throws RemoteException {
         switch(wifiLock.mMode) {
             case WifiManager.WIFI_MODE_FULL:
+            case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
                 mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource);
                 break;
             case WifiManager.WIFI_MODE_SCAN_ONLY:
@@ -1287,6 +1306,10 @@
             case WifiManager.WIFI_MODE_FULL:
                 ++mFullLocksAcquired;
                 break;
+            case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
+                ++mFullHighPerfLocksAcquired;
+                break;
+
             case WifiManager.WIFI_MODE_SCAN_ONLY:
                 ++mScanLocksAcquired;
                 break;
@@ -1356,6 +1379,9 @@
                     case WifiManager.WIFI_MODE_FULL:
                         ++mFullLocksReleased;
                         break;
+                    case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
+                        ++mFullHighPerfLocksReleased;
+                        break;
                     case WifiManager.WIFI_MODE_SCAN_ONLY:
                         ++mScanLocksReleased;
                         break;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 9bc24d2..c29e4a9 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -569,7 +569,7 @@
         void broadcastDragStartedLw(final float touchX, final float touchY) {
             // Cache a base-class instance of the clip metadata so that parceling
             // works correctly in calling out to the apps.
-            mDataDescription = new ClipDescription(mData);
+            mDataDescription = mData.getDescription();
             mNotifiedWindows.clear();
             mDragInProgress = true;
 
diff --git a/services/jni/com_android_server_location_GpsLocationProvider.cpp b/services/jni/com_android_server_location_GpsLocationProvider.cpp
index f5e17f5..a75e41d 100755
--- a/services/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -199,8 +199,6 @@
 
 static void agps_request_set_id(uint32_t flags)
 {
-    LOGD("agps_request_set_id: flags (%d)", flags);
-
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -208,8 +206,6 @@
 
 static void agps_request_ref_location(uint32_t flags)
 {
-    LOGD("agps_ref_location: flags (%d)", flags);
-
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 8ab5a10..df6aa51 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -424,6 +424,20 @@
         cb = (texture.NPOTAdjust ? texture.hScale : 1.0f);
     }
 
+    /*
+     * For the buffer transformation, we apply the rotation last.
+     * Since we're transforming the texture-coordinates, we need
+     * to apply the inverse of the buffer transformation:
+     *   inverse( FLIP_V -> FLIP_H -> ROT_90 )
+     *   <=> inverse( ROT_90 * FLIP_H * FLIP_V )
+     *    =  inverse(FLIP_V) * inverse(FLIP_H) * inverse(ROT_90)
+     *    =  FLIP_V * FLIP_H * ROT_270
+     *   <=> ROT_270 -> FLIP_H -> FLIP_V
+     *
+     * The rotation is performed first, in the texture coordinate space.
+     *
+     */
+
     struct TexCoords {
         GLfloat u;
         GLfloat v;
diff --git a/services/surfaceflinger/LayerBuffer.cpp b/services/surfaceflinger/LayerBuffer.cpp
index b7f9481..23506cf 100644
--- a/services/surfaceflinger/LayerBuffer.cpp
+++ b/services/surfaceflinger/LayerBuffer.cpp
@@ -676,8 +676,8 @@
                 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
                 // we need to combine the layer orientation and the
                 // user-requested orientation.
-                Transform finalTransform = Transform(mOrientation) *
-                        Transform(mLayer.getOrientation());
+                Transform finalTransform(Transform(mLayer.getOrientation()) *
+                        Transform(mOrientation));
                 overlay_dev->setParameter(overlay_dev, mOverlay,
                         OVERLAY_TRANSFORM, finalTransform.getOrientation());
                 overlay_dev->commit(overlay_dev, mOverlay);
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index f128429..0467a14 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -28,26 +28,40 @@
 
 // ---------------------------------------------------------------------------
 
-template <typename T> inline T min(T a, T b) {
+template <typename T>
+static inline T min(T a, T b) {
     return a<b ? a : b;
 }
-template <typename T> inline T min(T a, T b, T c) {
+template <typename T>
+static inline T min(T a, T b, T c) {
     return min(a, min(b, c));
 }
-template <typename T> inline T min(T a, T b, T c, T d) {
+template <typename T>
+static inline T min(T a, T b, T c, T d) {
     return min(a, b, min(c, d));
 }
 
-template <typename T> inline T max(T a, T b) {
+template <typename T>
+static inline T max(T a, T b) {
     return a>b ? a : b;
 }
-template <typename T> inline T max(T a, T b, T c) {
+template <typename T>
+static inline T max(T a, T b, T c) {
     return max(a, max(b, c));
 }
-template <typename T> inline T max(T a, T b, T c, T d) {
+template <typename T>
+static inline T max(T a, T b, T c, T d) {
     return max(a, b, max(c, d));
 }
 
+template <typename T>
+static inline
+void swap(T& a, T& b) {
+    T t(a);
+    a = b;
+    b = t;
+}
+
 // ---------------------------------------------------------------------------
 
 Transform::Transform() {
@@ -160,6 +174,11 @@
     }
 
     Transform H, V, R;
+    if (flags & ROT_90) {
+        // w & h are inverted when rotating by 90 degrees
+        swap(w, h);
+    }
+
     if (flags & FLIP_H) {
         H.mType = (FLIP_H << 8) | SCALE;
         H.mType |= isZero(w) ? IDENTITY : TRANSLATE;
@@ -177,14 +196,15 @@
     }
 
     if (flags & ROT_90) {
+        const float original_w = h;
         R.mType = (ROT_90 << 8) | ROTATE;
-        R.mType |= isZero(w) ? IDENTITY : TRANSLATE;
+        R.mType |= isZero(original_w) ? IDENTITY : TRANSLATE;
         mat33& M(R.mMatrix);
-        M[0][0] = 0;    M[1][0] =-1;    M[2][0] = w;
+        M[0][0] = 0;    M[1][0] =-1;    M[2][0] = original_w;
         M[0][1] = 1;    M[1][1] = 0;
     }
 
-    *this = ((H*V)*R);
+    *this = (R*(H*V));
     return NO_ERROR;
 }
 
@@ -282,8 +302,8 @@
             }
         } else if (isZero(a) && isZero(d)) {
             flags |= ROT_90;
-            if (b>0)    flags |= FLIP_H;
-            if (c<0)    flags |= FLIP_V;
+            if (b>0)    flags |= FLIP_V;
+            if (c<0)    flags |= FLIP_H;
             if (!absIsOne(b) || !absIsOne(c)) {
                 scale = true;
             }
diff --git a/tests/StatusBar/res/drawable-mdpi/icon1.png b/tests/StatusBar/res/drawable-mdpi/icon1.png
index abfb6fa..a999834 100644
--- a/tests/StatusBar/res/drawable-mdpi/icon1.png
+++ b/tests/StatusBar/res/drawable-mdpi/icon1.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/icon2.png b/tests/StatusBar/res/drawable-mdpi/icon2.png
index 564b38b..b7763cb 100644
--- a/tests/StatusBar/res/drawable-mdpi/icon2.png
+++ b/tests/StatusBar/res/drawable-mdpi/icon2.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notification0.png b/tests/StatusBar/res/drawable-mdpi/notification0.png
new file mode 100644
index 0000000..39794f3
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notification0.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notification1.png b/tests/StatusBar/res/drawable-mdpi/notification1.png
new file mode 100644
index 0000000..b7bbe2b
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notification1.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notification2.png b/tests/StatusBar/res/drawable-mdpi/notification2.png
new file mode 100644
index 0000000..b014280
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notification2.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notification3.png b/tests/StatusBar/res/drawable-mdpi/notification3.png
new file mode 100644
index 0000000..2c618211
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notification3.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notification4.png b/tests/StatusBar/res/drawable-mdpi/notification4.png
new file mode 100644
index 0000000..1e04793
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notification4.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notification5.png b/tests/StatusBar/res/drawable-mdpi/notification5.png
new file mode 100644
index 0000000..f05dfe5
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notification5.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notification6.png b/tests/StatusBar/res/drawable-mdpi/notification6.png
new file mode 100644
index 0000000..b807181
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notification6.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notification7.png b/tests/StatusBar/res/drawable-mdpi/notification7.png
new file mode 100644
index 0000000..63b2544
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notification7.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notification8.png b/tests/StatusBar/res/drawable-mdpi/notification8.png
new file mode 100644
index 0000000..13c1499
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notification8.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notification9.png b/tests/StatusBar/res/drawable-mdpi/notification9.png
new file mode 100644
index 0000000..587d04c
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notification9.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/notificationx.png b/tests/StatusBar/res/drawable-mdpi/notificationx.png
new file mode 100644
index 0000000..4df9804
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/notificationx.png
Binary files differ
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 9c267d6..38ee1b8 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -44,6 +44,20 @@
     long mActivityCreateTime = System.currentTimeMillis();
     long mChronometerBase = 0;
 
+    final int[] kNumberedIconResIDs = {
+        R.drawable.notification0,
+        R.drawable.notification1,
+        R.drawable.notification2,
+        R.drawable.notification3,
+        R.drawable.notification4,
+        R.drawable.notification5,
+        R.drawable.notification6,
+        R.drawable.notification7,
+        R.drawable.notification8,
+        R.drawable.notification9
+    };
+    final int kUnnumberedIconResID = R.drawable.notificationx;
+
     @Override
     protected String tag() {
         return TAG;
@@ -708,7 +722,8 @@
         new Test("Ten Notifications") {
             public void run() {
                 for (int i = 0; i < 2; i++) {
-                    Notification n = new Notification(NotificationTestList.this, R.drawable.icon2,
+                    Notification n = new Notification(NotificationTestList.this,
+                            kNumberedIconResIDs[i],
                             null, System.currentTimeMillis(), "Persistent #" + i,
                             "Notify me!!!" + i, null);
                     n.flags |= Notification.FLAG_ONGOING_EVENT;
@@ -716,7 +731,8 @@
                     mNM.notify((i+1)*10, n);
                 }
                 for (int i = 2; i < 10; i++) {
-                    Notification n = new Notification(NotificationTestList.this, R.drawable.icon2,
+                    Notification n = new Notification(NotificationTestList.this,
+                            kNumberedIconResIDs[i],
                             null, System.currentTimeMillis(), "Persistent #" + i,
                             "Notify me!!!" + i, null);
                     n.number = i;
@@ -733,6 +749,13 @@
             }
         },
         
+        new Test("Cancel the other two notifications") {
+            public void run() {
+                mNM.cancel(10);
+                mNM.cancel(100);
+            }
+        },
+        
         new Test("Persistent with numbers 1") {
             public void run() {
                 mNM.notify(1, notificationWithNumbers(1));
@@ -776,8 +799,14 @@
     };
 
     private Notification notificationWithNumbers(int num) {
-        Notification n = new Notification(this, R.drawable.icon2, null, System.currentTimeMillis(),
-                "Persistent #2", "Notify me!!!", null);
+        Notification n = new Notification(this,
+                (num >= 0 && num < kNumberedIconResIDs.length)
+                    ? kNumberedIconResIDs[num]
+                    : kUnnumberedIconResID,
+                null,
+                System.currentTimeMillis(),
+                "Notification", "Number=" + num,
+                null);
         n.number = num;
         return n;
     }
diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath
index 70140d8..aeeffa6 100644
--- a/tools/layoutlib/bridge/.classpath
+++ b/tools/layoutlib/bridge/.classpath
@@ -6,7 +6,7 @@
 	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
 	<classpathentry kind="var" path="ANDROID_SRC/prebuilt/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
 	<classpathentry kind="var" path="ANDROID_SRC/prebuilt/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_SRC/dalvik/libcore/xml/src/main/java"/>
-	<classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/layoutlib.jar" sourcepath="/ANDROID_SRC/frameworks/base/core/java"/>
 	<classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/ninepatch.jar" sourcepath="/ANDROID_SRC/development/tools/ninepatch/src"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas.java b/tools/layoutlib/bridge/src/android/graphics/Canvas.java
index 1e1aba9..0dccc0d6 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas.java
@@ -18,13 +18,6 @@
 
 import com.android.layoutlib.api.ILayoutLog;
 
-import android.graphics.DrawFilter;
-import android.graphics.Picture;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Region;
-import android.graphics.Xfermode;
 import android.graphics.Paint.Align;
 import android.graphics.Paint.FontInfo;
 import android.graphics.Paint.Style;
@@ -42,8 +35,6 @@
 import java.util.List;
 import java.util.Stack;
 
-import javax.microedition.khronos.opengles.GL;
-
 /**
  * Re-implementation of the Canvas, 100% in java on top of a BufferedImage.
  */
@@ -509,7 +500,7 @@
             // get the Graphics2D current matrix
             AffineTransform currentTx = g.getTransform();
             // get the AffineTransform from the matrix
-            AffineTransform matrixTx = matrix.getTransform();
+            AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(matrix);
 
             // combine them so that the matrix is applied after.
             currentTx.preConcatenate(matrixTx);
@@ -969,9 +960,9 @@
         Graphics2D g = getGraphics2d();
 
         // and apply the matrix
-        g.setTransform(matrix.getTransform());
+        g.setTransform(Matrix_Delegate.getAffineTransform(matrix));
 
-        if (mLogger != null && matrix.hasPerspective()) {
+        if (mLogger != null && Matrix_Delegate.hasPerspective(matrix)) {
             mLogger.warning("android.graphics.Canvas#setMatrix(android.graphics.Matrix) only supports affine transformations in the Layout Editor.");
         }
     }
@@ -987,7 +978,7 @@
         // get its current matrix
         AffineTransform currentTx = g.getTransform();
         // get the AffineTransform of the given matrix
-        AffineTransform matrixTx = matrix.getTransform();
+        AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(matrix);
 
         // combine them so that the given matrix is applied after.
         currentTx.preConcatenate(matrixTx);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix.java b/tools/layoutlib/bridge/src/android/graphics/Matrix.java
deleted file mode 100644
index 9e30671..0000000
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix.java
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-
-
-/**
- * A matrix implementation overridden by the LayoutLib bridge.
- */
-public class Matrix extends _Original_Matrix {
-
-    float mValues[] = new float[9];
-
-    /**
-     * Create an identity matrix
-     */
-    public Matrix() {
-        reset();
-    }
-
-    /**
-     * Create a matrix that is a (deep) copy of src
-     * @param src The matrix to copy into this matrix
-     */
-    public Matrix(Matrix src) {
-        set(src);
-    }
-
-    /**
-     * Creates a Matrix object from the float array. The array becomes the internal storage
-     * of the object.
-     * @param data
-     */
-    private Matrix(float[] data) {
-        assert data.length != 9;
-        mValues = data;
-    }
-
-    //---------- Custom Methods
-
-    /**
-     * Adds the given transformation to the current Matrix
-     * <p/>This in effect does this = this*matrix
-     * @param matrix
-     */
-    private void addTransform(float[] matrix) {
-        float[] tmp = new float[9];
-
-        // first row
-        tmp[0] = matrix[0] * mValues[0] + matrix[1] * mValues[3] + matrix[2] * mValues[6];
-        tmp[1] = matrix[0] * mValues[1] + matrix[1] * mValues[4] + matrix[2] * mValues[7];
-        tmp[2] = matrix[0] * mValues[2] + matrix[1] * mValues[5] + matrix[2] * mValues[8];
-
-        // 2nd row
-        tmp[3] = matrix[3] * mValues[0] + matrix[4] * mValues[3] + matrix[5] * mValues[6];
-        tmp[4] = matrix[3] * mValues[1] + matrix[4] * mValues[4] + matrix[5] * mValues[7];
-        tmp[5] = matrix[3] * mValues[2] + matrix[4] * mValues[5] + matrix[5] * mValues[8];
-
-        // 3rd row
-        tmp[6] = matrix[6] * mValues[0] + matrix[7] * mValues[3] + matrix[8] * mValues[6];
-        tmp[7] = matrix[6] * mValues[1] + matrix[7] * mValues[4] + matrix[8] * mValues[7];
-        tmp[8] = matrix[6] * mValues[2] + matrix[7] * mValues[5] + matrix[8] * mValues[8];
-
-        // copy the result over to mValues
-        mValues = tmp;
-    }
-
-    public AffineTransform getTransform() {
-        // the AffineTransform constructor takes the value in a different order
-        // for a matrix [ 0 1 2 ]
-        //              [ 3 4 5 ]
-        // the order is 0, 3, 1, 4, 2, 5...
-        return new AffineTransform(mValues[0], mValues[3], mValues[1],
-                mValues[4], mValues[2], mValues[5]);
-    }
-
-    public boolean hasPerspective() {
-        return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
-    }
-
-    //----------
-
-    /**
-     * Returns true if the matrix is identity.
-     * This maybe faster than testing if (getType() == 0)
-     */
-    @Override
-    public boolean isIdentity() {
-        for (int i = 0, k = 0; i < 3; i++) {
-            for (int j = 0; j < 3; j++, k++) {
-                if (mValues[k] != ((i==j) ? 1 : 0)) {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns true if will map a rectangle to another rectangle. This can be
-     * true if the matrix is identity, scale-only, or rotates a multiple of 90
-     * degrees.
-     */
-    @Override
-    public boolean rectStaysRect() {
-        return (computeTypeMask() & kRectStaysRect_Mask) != 0;
-    }
-
-    /**
-     * (deep) copy the src matrix into this matrix. If src is null, reset this
-     * matrix to the identity matrix.
-     */
-    public void set(Matrix src) {
-        if (src == null) {
-            reset();
-        } else {
-            System.arraycopy(src.mValues, 0, mValues, 0, mValues.length);
-        }
-    }
-
-    @Override
-    public void set(_Original_Matrix src) {
-        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
-    }
-
-    /** Returns true if obj is a Matrix and its values equal our values.
-    */
-    @Override
-    public boolean equals(Object obj) {
-        if (obj != null && obj instanceof Matrix) {
-            Matrix matrix = (Matrix)obj;
-            for (int i = 0 ; i < 9 ; i++) {
-                if (mValues[i] != matrix.mValues[i]) {
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-    /** Set the matrix to identity */
-    @Override
-    public void reset() {
-        for (int i = 0, k = 0; i < 3; i++) {
-            for (int j = 0; j < 3; j++, k++) {
-                mValues[k] = ((i==j) ? 1 : 0);
-            }
-        }
-    }
-
-    /** Set the matrix to translate by (dx, dy). */
-    @Override
-    public void setTranslate(float dx, float dy) {
-        mValues[0] = 1;
-        mValues[1] = 0;
-        mValues[2] = dx;
-        mValues[3] = 0;
-        mValues[4] = 1;
-        mValues[5] = dy;
-        mValues[6] = 0;
-        mValues[7] = 0;
-        mValues[8] = 1;
-    }
-
-    /**
-     * Set the matrix to scale by sx and sy, with a pivot point at (px, py).
-     * The pivot point is the coordinate that should remain unchanged by the
-     * specified transformation.
-     */
-    @Override
-    public void setScale(float sx, float sy, float px, float py) {
-        // TODO: do it in one pass
-
-        // translate so that the pivot is in 0,0
-        mValues[0] = 1;
-        mValues[1] = 0;
-        mValues[2] = -px;
-        mValues[3] = 0;
-        mValues[4] = 1;
-        mValues[5] = -py;
-        mValues[6] = 0;
-        mValues[7] = 0;
-        mValues[8] = 1;
-
-        // scale
-        addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 });
-        // translate back the pivot
-        addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-    }
-
-    /** Set the matrix to scale by sx and sy. */
-    @Override
-    public void setScale(float sx, float sy) {
-        mValues[0] = sx;
-        mValues[1] = 0;
-        mValues[2] = 0;
-        mValues[3] = 0;
-        mValues[4] = sy;
-        mValues[5] = 0;
-        mValues[6] = 0;
-        mValues[7] = 0;
-        mValues[8] = 1;
-    }
-
-    /**
-     * Set the matrix to rotate by the specified number of degrees, with a pivot
-     * point at (px, py). The pivot point is the coordinate that should remain
-     * unchanged by the specified transformation.
-     */
-    @Override
-    public void setRotate(float degrees, float px, float py) {
-        // TODO: do it in one pass
-
-        // translate so that the pivot is in 0,0
-        mValues[0] = 1;
-        mValues[1] = 0;
-        mValues[2] = -px;
-        mValues[3] = 0;
-        mValues[4] = 1;
-        mValues[5] = -py;
-        mValues[6] = 0;
-        mValues[7] = 0;
-        mValues[8] = 1;
-
-        // scale
-        double rad = Math.toRadians(degrees);
-        float cos = (float)Math.cos(rad);
-        float sin = (float)Math.sin(rad);
-        addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
-        // translate back the pivot
-        addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-    }
-
-    /**
-     * Set the matrix to rotate about (0,0) by the specified number of degrees.
-     */
-    @Override
-    public void setRotate(float degrees) {
-        double rad = Math.toRadians(degrees);
-        float cos = (float)Math.cos(rad);
-        float sin = (float)Math.sin(rad);
-
-        mValues[0] = cos;
-        mValues[1] = -sin;
-        mValues[2] = 0;
-        mValues[3] = sin;
-        mValues[4] = cos;
-        mValues[5] = 0;
-        mValues[6] = 0;
-        mValues[7] = 0;
-        mValues[8] = 1;
-    }
-
-    /**
-     * Set the matrix to rotate by the specified sine and cosine values, with a
-     * pivot point at (px, py). The pivot point is the coordinate that should
-     * remain unchanged by the specified transformation.
-     */
-    @Override
-    public void setSinCos(float sinValue, float cosValue, float px, float py) {
-        // TODO: do it in one pass
-
-        // translate so that the pivot is in 0,0
-        mValues[0] = 1;
-        mValues[1] = 0;
-        mValues[2] = -px;
-        mValues[3] = 0;
-        mValues[4] = 1;
-        mValues[5] = -py;
-        mValues[6] = 0;
-        mValues[7] = 0;
-        mValues[8] = 1;
-
-        // scale
-        addTransform(new float[] { cosValue, -sinValue, 0, sinValue, cosValue, 0, 0, 0, 1 });
-        // translate back the pivot
-        addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-    }
-
-    /** Set the matrix to rotate by the specified sine and cosine values. */
-    @Override
-    public void setSinCos(float sinValue, float cosValue) {
-        mValues[0] = cosValue;
-        mValues[1] = -sinValue;
-        mValues[2] = 0;
-        mValues[3] = sinValue;
-        mValues[4] = cosValue;
-        mValues[5] = 0;
-        mValues[6] = 0;
-        mValues[7] = 0;
-        mValues[8] = 1;
-    }
-
-    /**
-     * Set the matrix to skew by sx and sy, with a pivot point at (px, py).
-     * The pivot point is the coordinate that should remain unchanged by the
-     * specified transformation.
-     */
-    @Override
-    public void setSkew(float kx, float ky, float px, float py) {
-        // TODO: do it in one pass
-
-        // translate so that the pivot is in 0,0
-        mValues[0] = 1;
-        mValues[1] = 0;
-        mValues[2] = -px;
-        mValues[3] = 0;
-        mValues[4] = 1;
-        mValues[5] = -py;
-        mValues[6] = 0;
-        mValues[7] = 0;
-        mValues[8] = 1;
-
-        // scale
-        addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
-        // translate back the pivot
-        addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-    }
-
-    /** Set the matrix to skew by sx and sy. */
-    @Override
-    public void setSkew(float kx, float ky) {
-        mValues[0] = 1;
-        mValues[1] = kx;
-        mValues[2] = -0;
-        mValues[3] = ky;
-        mValues[4] = 1;
-        mValues[5] = 0;
-        mValues[6] = 0;
-        mValues[7] = 0;
-        mValues[8] = 1;
-    }
-
-    /**
-     * Set the matrix to the concatenation of the two specified matrices,
-     * returning true if the the result can be represented. Either of the two
-     * matrices may also be the target matrix. this = a * b
-     */
-    public boolean setConcat(Matrix a, Matrix b) {
-        if (a == this) {
-            preConcat(b);
-        } else if (b == this) {
-            postConcat(b);
-        } else {
-            Matrix tmp = new Matrix(b);
-            tmp.addTransform(a.mValues);
-            set(tmp);
-        }
-
-        return true;
-    }
-
-    @Override
-    public boolean setConcat(_Original_Matrix a, _Original_Matrix b) {
-        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
-    }
-
-    /**
-     * Preconcats the matrix with the specified translation.
-     * M' = M * T(dx, dy)
-     */
-    @Override
-    public boolean preTranslate(float dx, float dy) {
-        // create a matrix that will be multiply by this
-        Matrix m = new Matrix(new float[] { 1, 0, dx, 0, 1, dy, 0, 0, 1 });
-        m.addTransform(this.mValues);
-
-        System.arraycopy(m.mValues, 0, mValues, 0, 9);
-        return true;
-    }
-
-    /**
-     * Preconcats the matrix with the specified scale.
-     * M' = M * S(sx, sy, px, py)
-     */
-    @Override
-    public boolean preScale(float sx, float sy, float px, float py) {
-        Matrix m = new Matrix();
-        m.setScale(sx, sy, px, py);
-        m.addTransform(mValues);
-        set(m);
-
-        return true;
-    }
-
-    /**
-     * Preconcats the matrix with the specified scale.
-     * M' = M * S(sx, sy)
-     */
-    @Override
-    public boolean preScale(float sx, float sy) {
-        Matrix m = new Matrix();
-        m.setScale(sx, sy);
-        m.addTransform(mValues);
-        set(m);
-
-        return true;
-    }
-
-    /**
-     * Preconcats the matrix with the specified rotation.
-     * M' = M * R(degrees, px, py)
-     */
-    @Override
-    public boolean preRotate(float degrees, float px, float py) {
-        Matrix m = new Matrix();
-        m.setRotate(degrees, px, py);
-        m.addTransform(mValues);
-        set(m);
-
-        return true;
-    }
-
-    /**
-     * Preconcats the matrix with the specified rotation.
-     * M' = M * R(degrees)
-     */
-    @Override
-    public boolean preRotate(float degrees) {
-        Matrix m = new Matrix();
-        m.setRotate(degrees);
-        m.addTransform(mValues);
-        set(m);
-
-        return true;
-    }
-
-    /**
-     * Preconcats the matrix with the specified skew.
-     * M' = M * K(kx, ky, px, py)
-     */
-    @Override
-    public boolean preSkew(float kx, float ky, float px, float py) {
-        Matrix m = new Matrix();
-        m.setSkew(kx, ky, px, py);
-        m.addTransform(mValues);
-        set(m);
-
-        return true;
-    }
-
-    /**
-     * Preconcats the matrix with the specified skew.
-     * M' = M * K(kx, ky)
-     */
-    @Override
-    public boolean preSkew(float kx, float ky) {
-        Matrix m = new Matrix();
-        m.setSkew(kx, ky);
-        m.addTransform(mValues);
-        set(m);
-
-        return true;
-    }
-
-    /**
-     * Preconcats the matrix with the specified matrix.
-     * M' = M * other
-     */
-    public boolean preConcat(Matrix other) {
-        Matrix m = new Matrix(other);
-        other.addTransform(mValues);
-        set(m);
-
-        return true;
-    }
-
-    @Override
-    public boolean preConcat(_Original_Matrix other) {
-        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
-    }
-
-    /**
-     * Postconcats the matrix with the specified translation.
-     * M' = T(dx, dy) * M
-     */
-    @Override
-    public boolean postTranslate(float dx, float dy) {
-        addTransform(new float[] { 1, 0, dx, 0, 1, dy, 0, 0, 1 });
-        return true;
-    }
-
-    /**
-     * Postconcats the matrix with the specified scale.
-     * M' = S(sx, sy, px, py) * M
-     */
-    @Override
-    public boolean postScale(float sx, float sy, float px, float py) {
-        // TODO: do it in one pass
-        // translate so that the pivot is in 0,0
-        addTransform(new float[] { 1, 0, -px, 0, 1, py, 0, 0, 1 });
-        // scale
-        addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 });
-        // translate back the pivot
-        addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-
-        return true;
-    }
-
-    /**
-     * Postconcats the matrix with the specified scale.
-     * M' = S(sx, sy) * M
-     */
-    @Override
-    public boolean postScale(float sx, float sy) {
-        addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 });
-        return true;
-    }
-
-    /**
-     * Postconcats the matrix with the specified rotation.
-     * M' = R(degrees, px, py) * M
-     */
-    @Override
-    public boolean postRotate(float degrees, float px, float py) {
-        // TODO: do it in one pass
-        // translate so that the pivot is in 0,0
-        addTransform(new float[] { 1, 0, -px, 0, 1, py, 0, 0, 1 });
-        // scale
-        double rad = Math.toRadians(degrees);
-        float cos = (float)Math.cos(rad);
-        float sin = (float)Math.sin(rad);
-        addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
-        // translate back the pivot
-        addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-
-        return true;
-    }
-
-    /**
-     * Postconcats the matrix with the specified rotation.
-     * M' = R(degrees) * M
-     */
-    @Override
-    public boolean postRotate(float degrees) {
-        double rad = Math.toRadians(degrees);
-        float cos = (float)Math.cos(rad);
-        float sin = (float)Math.sin(rad);
-        addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
-
-        return true;
-    }
-
-    /**
-     * Postconcats the matrix with the specified skew.
-     * M' = K(kx, ky, px, py) * M
-     */
-    @Override
-    public boolean postSkew(float kx, float ky, float px, float py) {
-        // TODO: do it in one pass
-        // translate so that the pivot is in 0,0
-        addTransform(new float[] { 1, 0, -px, 0, 1, py, 0, 0, 1 });
-        // scale
-        addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
-        // translate back the pivot
-        addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-
-        return true;
-    }
-
-    /**
-     * Postconcats the matrix with the specified skew.
-     * M' = K(kx, ky) * M
-     */
-    @Override
-    public boolean postSkew(float kx, float ky) {
-        addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
-
-        return true;
-    }
-
-    /**
-     * Postconcats the matrix with the specified matrix.
-     * M' = other * M
-     */
-    public boolean postConcat(Matrix other) {
-        addTransform(other.mValues);
-
-        return true;
-    }
-
-    @Override
-    public boolean postConcat(_Original_Matrix other) {
-        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
-    }
-
-    /** Controlls how the src rect should align into the dst rect for
-        setRectToRect().
-    */
-    public enum ScaleToFit {
-        /**
-         * Scale in X and Y independently, so that src matches dst exactly.
-         * This may change the aspect ratio of the src.
-         */
-        FILL    (0),
-        /**
-         * Compute a scale that will maintain the original src aspect ratio,
-         * but will also ensure that src fits entirely inside dst. At least one
-         * axis (X or Y) will fit exactly. START aligns the result to the
-         * left and top edges of dst.
-         */
-        START   (1),
-        /**
-         * Compute a scale that will maintain the original src aspect ratio,
-         * but will also ensure that src fits entirely inside dst. At least one
-         * axis (X or Y) will fit exactly. The result is centered inside dst.
-         */
-        CENTER  (2),
-        /**
-         * Compute a scale that will maintain the original src aspect ratio,
-         * but will also ensure that src fits entirely inside dst. At least one
-         * axis (X or Y) will fit exactly. END aligns the result to the
-         * right and bottom edges of dst.
-         */
-        END     (3);
-
-        // the native values must match those in SkMatrix.h
-        ScaleToFit(int nativeInt) {
-            this.nativeInt = nativeInt;
-        }
-        final int nativeInt;
-    }
-
-    /**
-     * Set the matrix to the scale and translate values that map the source
-     * rectangle to the destination rectangle, returning true if the result
-     * can be represented.
-     *
-     * @param src the source rectangle to map from.
-     * @param dst the destination rectangle to map to.
-     * @param stf the ScaleToFit option
-     * @return true if the matrix can be represented by the rectangle mapping.
-     */
-    public boolean setRectToRect(RectF src, RectF dst, ScaleToFit stf) {
-        if (dst == null || src == null) {
-            throw new NullPointerException();
-        }
-
-        if (src.isEmpty()) {
-            reset();
-            return false;
-        }
-
-        if (dst.isEmpty()) {
-            mValues[0] = mValues[1] = mValues[2] = mValues[3] = mValues[4] = mValues[5]
-               = mValues[6] = mValues[7] = 0;
-            mValues[8] = 1;
-        } else {
-            float    tx, sx = dst.width() / src.width();
-            float    ty, sy = dst.height() / src.height();
-            boolean  xLarger = false;
-
-            if (stf != ScaleToFit.FILL) {
-                if (sx > sy) {
-                    xLarger = true;
-                    sx = sy;
-                } else {
-                    sy = sx;
-                }
-            }
-
-            tx = dst.left - src.left * sx;
-            ty = dst.top - src.top * sy;
-            if (stf == ScaleToFit.CENTER || stf == ScaleToFit.END) {
-                float diff;
-
-                if (xLarger) {
-                    diff = dst.width() - src.width() * sy;
-                } else {
-                    diff = dst.height() - src.height() * sy;
-                }
-
-                if (stf == ScaleToFit.CENTER) {
-                    diff = diff / 2;
-                }
-
-                if (xLarger) {
-                    tx += diff;
-                } else {
-                    ty += diff;
-                }
-            }
-
-            mValues[0] = sx;
-            mValues[4] = sy;
-            mValues[2] = tx;
-            mValues[5] = ty;
-            mValues[1]  = mValues[3] = mValues[6] = mValues[7] = 0;
-
-        }
-        // shared cleanup
-        mValues[8] = 1;
-        return true;
-    }
-
-    @Override
-    public boolean setRectToRect(RectF src, RectF dst, _Original_Matrix.ScaleToFit stf) {
-        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
-    }
-
-    /**
-     * Set the matrix such that the specified src points would map to the
-     * specified dst points. The "points" are represented as an array of floats,
-     * order [x0, y0, x1, y1, ...], where each "point" is 2 float values.
-     *
-     * @param src   The array of src [x,y] pairs (points)
-     * @param srcIndex Index of the first pair of src values
-     * @param dst   The array of dst [x,y] pairs (points)
-     * @param dstIndex Index of the first pair of dst values
-     * @param pointCount The number of pairs/points to be used. Must be [0..4]
-     * @return true if the matrix was set to the specified transformation
-     */
-    @Override
-    public boolean setPolyToPoly(float[] src, int srcIndex,
-                                 float[] dst, int dstIndex,
-                                 int pointCount) {
-        if (pointCount > 4) {
-            throw new IllegalArgumentException();
-        }
-        checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
-        throw new UnsupportedOperationException("STUB NEEDED");
-    }
-
-    /**
-     * If this matrix can be inverted, return true and if inverse is not null,
-     * set inverse to be the inverse of this matrix. If this matrix cannot be
-     * inverted, ignore inverse and return false.
-     */
-    public boolean invert(Matrix inverse) {
-        if (inverse == null) {
-            return false;
-        }
-
-        try {
-            AffineTransform affineTransform = getTransform();
-            AffineTransform inverseTransform = affineTransform.createInverse();
-            inverse.mValues[0] = (float)inverseTransform.getScaleX();
-            inverse.mValues[1] = (float)inverseTransform.getShearX();
-            inverse.mValues[2] = (float)inverseTransform.getTranslateX();
-            inverse.mValues[3] = (float)inverseTransform.getScaleX();
-            inverse.mValues[4] = (float)inverseTransform.getShearY();
-            inverse.mValues[5] = (float)inverseTransform.getTranslateY();
-
-            return true;
-        } catch (NoninvertibleTransformException e) {
-            return false;
-        }
-    }
-
-    @Override
-    public boolean invert(_Original_Matrix inverse) {
-        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
-    }
-
-    /**
-    * Apply this matrix to the array of 2D points specified by src, and write
-     * the transformed points into the array of points specified by dst. The
-     * two arrays represent their "points" as pairs of floats [x, y].
-     *
-     * @param dst   The array of dst points (x,y pairs)
-     * @param dstIndex The index of the first [x,y] pair of dst floats
-     * @param src   The array of src points (x,y pairs)
-     * @param srcIndex The index of the first [x,y] pair of src floats
-     * @param pointCount The number of points (x,y pairs) to transform
-     */
-    @Override
-    public void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
-                          int pointCount) {
-        checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
-
-        for (int i = 0 ; i < pointCount ; i++) {
-            // just in case we are doing in place, we better put this in temp vars
-            float x = mValues[0] * src[i + srcIndex] +
-                      mValues[1] * src[i + srcIndex + 1] +
-                      mValues[2];
-            float y = mValues[3] * src[i + srcIndex] +
-                      mValues[4] * src[i + srcIndex + 1] +
-                      mValues[5];
-
-            dst[i + dstIndex]     = x;
-            dst[i + dstIndex + 1] = y;
-        }
-    }
-
-    /**
-    * Apply this matrix to the array of 2D vectors specified by src, and write
-     * the transformed vectors into the array of vectors specified by dst. The
-     * two arrays represent their "vectors" as pairs of floats [x, y].
-     *
-     * @param dst   The array of dst vectors (x,y pairs)
-     * @param dstIndex The index of the first [x,y] pair of dst floats
-     * @param src   The array of src vectors (x,y pairs)
-     * @param srcIndex The index of the first [x,y] pair of src floats
-     * @param vectorCount The number of vectors (x,y pairs) to transform
-     */
-    @Override
-    public void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex,
-                          int vectorCount) {
-        checkPointArrays(src, srcIndex, dst, dstIndex, vectorCount);
-        throw new UnsupportedOperationException("STUB NEEDED");
-    }
-
-    /**
-     * Apply this matrix to the array of 2D points specified by src, and write
-     * the transformed points into the array of points specified by dst. The
-     * two arrays represent their "points" as pairs of floats [x, y].
-     *
-     * @param dst   The array of dst points (x,y pairs)
-     * @param src   The array of src points (x,y pairs)
-     */
-    @Override
-    public void mapPoints(float[] dst, float[] src) {
-        if (dst.length != src.length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-        mapPoints(dst, 0, src, 0, dst.length >> 1);
-    }
-
-    /**
-     * Apply this matrix to the array of 2D vectors specified by src, and write
-     * the transformed vectors into the array of vectors specified by dst. The
-     * two arrays represent their "vectors" as pairs of floats [x, y].
-     *
-     * @param dst   The array of dst vectors (x,y pairs)
-     * @param src   The array of src vectors (x,y pairs)
-     */
-    @Override
-    public void mapVectors(float[] dst, float[] src) {
-        if (dst.length != src.length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-        mapVectors(dst, 0, src, 0, dst.length >> 1);
-    }
-
-    /**
-     * Apply this matrix to the array of 2D points, and write the transformed
-     * points back into the array
-     *
-     * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
-     */
-    @Override
-    public void mapPoints(float[] pts) {
-        mapPoints(pts, 0, pts, 0, pts.length >> 1);
-    }
-
-    /**
-     * Apply this matrix to the array of 2D vectors, and write the transformed
-     * vectors back into the array.
-     * @param vecs The array [x0, y0, x1, y1, ...] of vectors to transform.
-     */
-    @Override
-    public void mapVectors(float[] vecs) {
-        mapVectors(vecs, 0, vecs, 0, vecs.length >> 1);
-    }
-
-    /**
-     * Apply this matrix to the src rectangle, and write the transformed
-     * rectangle into dst. This is accomplished by transforming the 4 corners of
-     * src, and then setting dst to the bounds of those points.
-     *
-     * @param dst Where the transformed rectangle is written.
-     * @param src The original rectangle to be transformed.
-     * @return the result of calling rectStaysRect()
-     */
-    @Override
-    public boolean mapRect(RectF dst, RectF src) {
-        if (dst == null || src == null) {
-            throw new NullPointerException();
-        }
-
-        // array with 4 corners
-        float[] corners = new float[] {
-                src.left, src.top,
-                src.right, src.top,
-                src.right, src.bottom,
-                src.left, src.bottom,
-        };
-
-        // apply the transform to them.
-        mapPoints(corners);
-
-        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
-        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
-        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
-
-        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
-        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
-
-        return rectStaysRect();
-    }
-
-    /**
-     * Apply this matrix to the rectangle, and write the transformed rectangle
-     * back into it. This is accomplished by transforming the 4 corners of rect,
-     * and then setting it to the bounds of those points
-     *
-     * @param rect The rectangle to transform.
-     * @return the result of calling rectStaysRect()
-     */
-    @Override
-    public boolean mapRect(RectF rect) {
-        return mapRect(rect, rect);
-    }
-
-    /**
-     * Return the mean radius of a circle after it has been mapped by
-     * this matrix. NOTE: in perspective this value assumes the circle
-     * has its center at the origin.
-     */
-    @Override
-    public float mapRadius(float radius) {
-        throw new UnsupportedOperationException("STUB NEEDED");
-    }
-
-    /** Copy 9 values from the matrix into the array.
-    */
-    @Override
-    public void getValues(float[] values) {
-        if (values.length < 9) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-        System.arraycopy(mValues, 0, values, 0, mValues.length);
-    }
-
-    /** Copy 9 values from the array into the matrix.
-        Depending on the implementation of Matrix, these may be
-        transformed into 16.16 integers in the Matrix, such that
-        a subsequent call to getValues() will not yield exactly
-        the same values.
-    */
-    @Override
-    public void setValues(float[] values) {
-        if (values.length < 9) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-        System.arraycopy(values, 0, mValues, 0, mValues.length);
-    }
-
-    @SuppressWarnings("unused")
-    private final static int kIdentity_Mask      = 0;
-    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
-    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
-    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
-    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
-    private final static int kRectStaysRect_Mask = 0x10;
-    @SuppressWarnings("unused")
-    private final static int kUnknown_Mask       = 0x80;
-
-    @SuppressWarnings("unused")
-    private final static int kAllMasks           = kTranslate_Mask |
-                                                     kScale_Mask |
-                                                     kAffine_Mask |
-                                                     kPerspective_Mask |
-                                                     kRectStaysRect_Mask;
-
-    // these guys align with the masks, so we can compute a mask from a variable 0/1
-    @SuppressWarnings("unused")
-    private final static int kTranslate_Shift = 0;
-    @SuppressWarnings("unused")
-    private final static int kScale_Shift = 1;
-    @SuppressWarnings("unused")
-    private final static int kAffine_Shift = 2;
-    @SuppressWarnings("unused")
-    private final static int kPerspective_Shift = 3;
-    private final static int kRectStaysRect_Shift = 4;
-
-    private int computeTypeMask() {
-        int mask = 0;
-
-        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
-            mask |= kPerspective_Mask;
-        }
-
-        if (mValues[2] != 0. || mValues[5] != 0.) {
-            mask |= kTranslate_Mask;
-        }
-
-        float m00 = mValues[0];
-        float m01 = mValues[1];
-        float m10 = mValues[3];
-        float m11 = mValues[4];
-
-        if (m01 != 0. || m10 != 0.) {
-            mask |= kAffine_Mask;
-        }
-
-        if (m00 != 1. || m11 != 1.) {
-            mask |= kScale_Mask;
-        }
-
-        if ((mask & kPerspective_Mask) == 0) {
-            // map non-zero to 1
-            int im00 = m00 != 0 ? 1 : 0;
-            int im01 = m01 != 0 ? 1 : 0;
-            int im10 = m10 != 0 ? 1 : 0;
-            int im11 = m11 != 0 ? 1 : 0;
-
-            // record if the (p)rimary and (s)econdary diagonals are all 0 or
-            // all non-zero (answer is 0 or 1)
-            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
-            int dp1 = im00 & im11;        // true if both are 1
-            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
-            int ds1 = im01 & im10;        // true if both are 1
-
-            // return 1 if primary is 1 and secondary is 0 or
-            // primary is 0 and secondary is 1
-            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
-        }
-
-        return mask;
-    }
-}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
new file mode 100644
index 0000000..ed2eff2
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -0,0 +1,1011 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+
+import com.android.layoutlib.bridge.DelegateManager;
+
+import android.graphics.Matrix.ScaleToFit;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+
+/**
+ * Delegate implementing the native methods of android.graphics.Matrix
+ *
+ * Through the layoutlib_create tool, the original native methods of Matrix have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original Matrix class.
+ *
+ * @see DelegateManager
+ *
+ */
+public final class Matrix_Delegate {
+
+    private final static int MATRIX_SIZE = 9;
+
+    // ---- delegate manager ----
+    private static final DelegateManager<Matrix_Delegate> sManager =
+            new DelegateManager<Matrix_Delegate>();
+
+    // ---- delegate data ----
+    private float mValues[] = new float[MATRIX_SIZE];
+
+    // ---- Public Helper methods ----
+
+    /**
+     * Returns an {@link AffineTransform} matching the given Matrix.
+     */
+    public static AffineTransform getAffineTransform(Matrix m) {
+        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
+        if (delegate == null) {
+            assert false;
+            return null;
+        }
+
+        return getAffineTransform(delegate);
+    }
+
+    public static boolean hasPerspective(Matrix m) {
+        Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
+        if (delegate == null) {
+            assert false;
+            return false;
+        }
+
+        return (delegate.mValues[6] != 0 || delegate.mValues[7] != 0 || delegate.mValues[8] != 1);
+    }
+
+
+    // ---- native methods ----
+
+    public static int native_create(int native_src_or_zero) {
+        // create the delegate
+        Matrix_Delegate newDelegate = new Matrix_Delegate();
+
+        // copy from values if needed.
+        if (native_src_or_zero > 0) {
+            Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero);
+            if (oldDelegate != null) {
+                System.arraycopy(
+                        oldDelegate.mValues, 0,
+                        newDelegate.mValues, 0,
+                        MATRIX_SIZE);
+            }
+        }
+
+        return sManager.addDelegate(newDelegate);
+    }
+
+    public static boolean native_isIdentity(int native_object) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        for (int i = 0, k = 0; i < 3; i++) {
+            for (int j = 0; j < 3; j++, k++) {
+                if (d.mValues[k] != ((i==j) ? 1 : 0)) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    public static boolean native_rectStaysRect(int native_object) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return true;
+        }
+
+        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
+    }
+
+    public static void native_reset(int native_object) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        reset(d.mValues);
+    }
+
+    public static void native_set(int native_object, int other) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        Matrix_Delegate src = sManager.getDelegate(other);
+        if (src == null) {
+            assert false;
+            return;
+        }
+
+        System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
+    }
+
+    public static void native_setTranslate(int native_object, float dx, float dy) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        setTranslate(d.mValues, dx, dy);
+    }
+
+    public static void native_setScale(int native_object, float sx, float sy, float px, float py) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        d.mValues = getScale(sx, sy, px, py);
+    }
+
+    public static void native_setScale(int native_object, float sx, float sy) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        d.mValues[0] = sx;
+        d.mValues[1] = 0;
+        d.mValues[2] = 0;
+        d.mValues[3] = 0;
+        d.mValues[4] = sy;
+        d.mValues[5] = 0;
+        d.mValues[6] = 0;
+        d.mValues[7] = 0;
+        d.mValues[8] = 1;
+    }
+
+    public static void native_setRotate(int native_object, float degrees, float px, float py) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        d.mValues = getRotate(degrees, px, py);
+    }
+
+    public static void native_setRotate(int native_object, float degrees) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        setRotate(d.mValues, degrees);
+    }
+
+    public static void native_setSinCos(int native_object, float sinValue, float cosValue,
+            float px, float py) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        // TODO: do it in one pass
+
+        // translate so that the pivot is in 0,0
+        setTranslate(d.mValues, -px, -py);
+
+        // scale
+        d.postTransform(getRotate(sinValue, cosValue));
+        // translate back the pivot
+        d.postTransform(getTranslate(px, py));
+    }
+
+    public static void native_setSinCos(int native_object, float sinValue, float cosValue) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        setRotate(d.mValues, sinValue, cosValue);
+    }
+
+    public static void native_setSkew(int native_object, float kx, float ky, float px, float py) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        d.mValues = getSkew(kx, ky, px, py);
+    }
+
+    public static void native_setSkew(int native_object, float kx, float ky) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        d.mValues[0] = 1;
+        d.mValues[1] = kx;
+        d.mValues[2] = -0;
+        d.mValues[3] = ky;
+        d.mValues[4] = 1;
+        d.mValues[5] = 0;
+        d.mValues[6] = 0;
+        d.mValues[7] = 0;
+        d.mValues[8] = 1;
+    }
+
+    public static boolean native_setConcat(int native_object, int a, int b) {
+        if (a == native_object) {
+            return native_preConcat(native_object, b);
+        } else if (b == native_object) {
+            return native_postConcat(native_object, a);
+        }
+
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        Matrix_Delegate a_mtx = sManager.getDelegate(a);
+        if (a_mtx == null) {
+            assert false;
+            return false;
+        }
+
+        Matrix_Delegate b_mtx = sManager.getDelegate(b);
+        if (b_mtx == null) {
+            assert false;
+            return false;
+        }
+
+        multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
+
+        return true;
+    }
+
+    public static boolean native_preTranslate(int native_object, float dx, float dy) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.preTransform(getTranslate(dx, dy));
+        return true;
+    }
+
+    public static boolean native_preScale(int native_object, float sx, float sy,
+            float px, float py) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.preTransform(getScale(sx, sy, px, py));
+        return true;
+    }
+
+    public static boolean native_preScale(int native_object, float sx, float sy) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.preTransform(getScale(sx, sy));
+        return true;
+    }
+
+    public static boolean native_preRotate(int native_object, float degrees, float px, float py) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.preTransform(getRotate(degrees, px, py));
+        return true;
+    }
+
+    public static boolean native_preRotate(int native_object, float degrees) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        double rad = Math.toRadians(degrees);
+        float sin = (float)Math.sin(rad);
+        float cos = (float)Math.cos(rad);
+
+        d.preTransform(getRotate(sin, cos));
+        return true;
+    }
+
+    public static boolean native_preSkew(int native_object, float kx, float ky,
+            float px, float py) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.preTransform(getSkew(kx, ky, px, py));
+        return true;
+    }
+
+    public static boolean native_preSkew(int native_object, float kx, float ky) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.preTransform(getSkew(kx, ky));
+        return true;
+    }
+
+    public static boolean native_preConcat(int native_object, int other_matrix) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        Matrix_Delegate other = sManager.getDelegate(other_matrix);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.preTransform(other.mValues);
+        return true;
+    }
+
+    public static boolean native_postTranslate(int native_object, float dx, float dy) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.postTransform(getTranslate(dx, dy));
+        return true;
+    }
+
+    public static boolean native_postScale(int native_object, float sx, float sy,
+            float px, float py) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.postTransform(getScale(sx, sy, px, py));
+        return true;
+    }
+
+    public static boolean native_postScale(int native_object, float sx, float sy) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.postTransform(getScale(sx, sy));
+        return true;
+    }
+
+    public static boolean native_postRotate(int native_object, float degrees, float px, float py) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.preTransform(getRotate(degrees, px, py));
+        return true;
+    }
+
+    public static boolean native_postRotate(int native_object, float degrees) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.postTransform(getRotate(degrees));
+        return true;
+    }
+
+    public static boolean native_postSkew(int native_object, float kx, float ky,
+            float px, float py) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.postTransform(getSkew(kx, ky, px, py));
+        return true;
+    }
+
+    public static boolean native_postSkew(int native_object, float kx, float ky) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.postTransform(getSkew(kx, ky));
+        return true;
+    }
+
+    public static boolean native_postConcat(int native_object, int other_matrix) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        Matrix_Delegate other = sManager.getDelegate(other_matrix);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        d.postTransform(other.mValues);
+        return true;
+    }
+
+    public static boolean native_setRectToRect(int native_object, RectF src, RectF dst, int stf) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        if (src.isEmpty()) {
+            reset(d.mValues);
+            return false;
+        }
+
+        if (dst.isEmpty()) {
+            d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5]
+               = d.mValues[6] = d.mValues[7] = 0;
+            d.mValues[8] = 1;
+        } else {
+            float    tx, sx = dst.width() / src.width();
+            float    ty, sy = dst.height() / src.height();
+            boolean  xLarger = false;
+
+            if (stf != ScaleToFit.FILL.nativeInt) {
+                if (sx > sy) {
+                    xLarger = true;
+                    sx = sy;
+                } else {
+                    sy = sx;
+                }
+            }
+
+            tx = dst.left - src.left * sx;
+            ty = dst.top - src.top * sy;
+            if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) {
+                float diff;
+
+                if (xLarger) {
+                    diff = dst.width() - src.width() * sy;
+                } else {
+                    diff = dst.height() - src.height() * sy;
+                }
+
+                if (stf == ScaleToFit.CENTER.nativeInt) {
+                    diff = diff / 2;
+                }
+
+                if (xLarger) {
+                    tx += diff;
+                } else {
+                    ty += diff;
+                }
+            }
+
+            d.mValues[0] = sx;
+            d.mValues[4] = sy;
+            d.mValues[2] = tx;
+            d.mValues[5] = ty;
+            d.mValues[1]  = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0;
+
+        }
+        // shared cleanup
+        d.mValues[8] = 1;
+        return true;
+    }
+
+    public static boolean native_setPolyToPoly(int native_object, float[] src, int srcIndex,
+            float[] dst, int dstIndex, int pointCount) {
+        // FIXME
+        throw new UnsupportedOperationException("NATIVE DELEGATE NEEDED");
+    }
+
+    public static boolean native_invert(int native_object, int inverse) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
+        if (inv_mtx == null) {
+            assert false;
+            return false;
+        }
+
+
+        try {
+            AffineTransform affineTransform = getAffineTransform(d);
+            AffineTransform inverseTransform = affineTransform.createInverse();
+            inv_mtx.mValues[0] = (float)inverseTransform.getScaleX();
+            inv_mtx.mValues[1] = (float)inverseTransform.getShearX();
+            inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX();
+            inv_mtx.mValues[3] = (float)inverseTransform.getScaleX();
+            inv_mtx.mValues[4] = (float)inverseTransform.getShearY();
+            inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY();
+
+            return true;
+        } catch (NoninvertibleTransformException e) {
+            return false;
+        }
+    }
+
+    public static void native_mapPoints(int native_object, float[] dst, int dstIndex,
+            float[] src, int srcIndex, int ptCount, boolean isPts) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        if (isPts) {
+            d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
+        } else {
+            // src is vectors
+            // FIXME
+            throw new UnsupportedOperationException("NATIVE DELEGATE NEEDED");
+        }
+    }
+
+    public static boolean native_mapRect(int native_object, RectF dst, RectF src) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return false;
+        }
+
+        // array with 4 corners
+        float[] corners = new float[] {
+                src.left, src.top,
+                src.right, src.top,
+                src.right, src.bottom,
+                src.left, src.bottom,
+        };
+
+        // apply the transform to them.
+        d.mapPoints(corners);
+
+        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
+        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
+        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
+
+        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
+        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
+
+
+        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
+    }
+
+    public static float native_mapRadius(int native_object, float radius) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    public static void native_getValues(int native_object, float[] values) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        System.arraycopy(d.mValues, 0, d.mValues, 0, MATRIX_SIZE);
+    }
+
+    public static void native_setValues(int native_object, float[] values) {
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            assert false;
+            return;
+        }
+
+        System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
+    }
+
+    public static boolean native_equals(int native_a, int native_b) {
+        Matrix_Delegate a = sManager.getDelegate(native_a);
+        if (a == null) {
+            assert false;
+            return false;
+        }
+
+        Matrix_Delegate b = sManager.getDelegate(native_b);
+        if (b == null) {
+            assert false;
+            return false;
+        }
+
+        for (int i = 0 ; i < MATRIX_SIZE ; i++) {
+            if (a.mValues[i] != b.mValues[i]) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public static void finalizer(int native_instance) {
+        sManager.removeDelegate(native_instance);
+    }
+
+    // ---- Private helper methods ----
+
+    private static AffineTransform getAffineTransform(Matrix_Delegate d) {
+        // the AffineTransform constructor takes the value in a different order
+        // for a matrix [ 0 1 2 ]
+        //              [ 3 4 5 ]
+        // the order is 0, 3, 1, 4, 2, 5...
+        return new AffineTransform(
+                d.mValues[0], d.mValues[3], d.mValues[1],
+                d.mValues[4], d.mValues[2], d.mValues[5]);
+    }
+
+
+    /**
+     * Reset a matrix to the identity
+     */
+    private static void reset(float[] mtx) {
+        for (int i = 0, k = 0; i < 3; i++) {
+            for (int j = 0; j < 3; j++, k++) {
+                mtx[k] = ((i==j) ? 1 : 0);
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private final static int kIdentity_Mask      = 0;
+    private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
+    private final static int kScale_Mask         = 0x02;  //!< set if the matrix has X or Y scale
+    private final static int kAffine_Mask        = 0x04;  //!< set if the matrix skews or rotates
+    private final static int kPerspective_Mask   = 0x08;  //!< set if the matrix is in perspective
+    private final static int kRectStaysRect_Mask = 0x10;
+    @SuppressWarnings("unused")
+    private final static int kUnknown_Mask       = 0x80;
+
+    @SuppressWarnings("unused")
+    private final static int kAllMasks           = kTranslate_Mask |
+                                                   kScale_Mask |
+                                                   kAffine_Mask |
+                                                   kPerspective_Mask |
+                                                   kRectStaysRect_Mask;
+
+    // these guys align with the masks, so we can compute a mask from a variable 0/1
+    @SuppressWarnings("unused")
+    private final static int kTranslate_Shift = 0;
+    @SuppressWarnings("unused")
+    private final static int kScale_Shift = 1;
+    @SuppressWarnings("unused")
+    private final static int kAffine_Shift = 2;
+    @SuppressWarnings("unused")
+    private final static int kPerspective_Shift = 3;
+    private final static int kRectStaysRect_Shift = 4;
+
+    private int computeTypeMask() {
+        int mask = 0;
+
+        if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
+            mask |= kPerspective_Mask;
+        }
+
+        if (mValues[2] != 0. || mValues[5] != 0.) {
+            mask |= kTranslate_Mask;
+        }
+
+        float m00 = mValues[0];
+        float m01 = mValues[1];
+        float m10 = mValues[3];
+        float m11 = mValues[4];
+
+        if (m01 != 0. || m10 != 0.) {
+            mask |= kAffine_Mask;
+        }
+
+        if (m00 != 1. || m11 != 1.) {
+            mask |= kScale_Mask;
+        }
+
+        if ((mask & kPerspective_Mask) == 0) {
+            // map non-zero to 1
+            int im00 = m00 != 0 ? 1 : 0;
+            int im01 = m01 != 0 ? 1 : 0;
+            int im10 = m10 != 0 ? 1 : 0;
+            int im11 = m11 != 0 ? 1 : 0;
+
+            // record if the (p)rimary and (s)econdary diagonals are all 0 or
+            // all non-zero (answer is 0 or 1)
+            int dp0 = (im00 | im11) ^ 1;  // true if both are 0
+            int dp1 = im00 & im11;        // true if both are 1
+            int ds0 = (im01 | im10) ^ 1;  // true if both are 0
+            int ds1 = im01 & im10;        // true if both are 1
+
+            // return 1 if primary is 1 and secondary is 0 or
+            // primary is 0 and secondary is 1
+            mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
+        }
+
+        return mask;
+    }
+
+    /**
+     * Adds the given transformation to the current Matrix
+     * <p/>This in effect does this = this*matrix
+     * @param matrix
+     */
+    private void postTransform(float[] matrix) {
+        float[] tmp = new float[9];
+        multiply(tmp, mValues, matrix);
+        mValues = tmp;
+    }
+
+    /**
+     * Adds the given transformation to the current Matrix
+     * <p/>This in effect does this = matrix*this
+     * @param matrix
+     */
+    private void preTransform(float[] matrix) {
+        float[] tmp = new float[9];
+        multiply(tmp, matrix, mValues);
+        mValues = tmp;
+    }
+
+    /**
+     * Apply this matrix to the array of 2D points specified by src, and write
+      * the transformed points into the array of points specified by dst. The
+      * two arrays represent their "points" as pairs of floats [x, y].
+      *
+      * @param dst   The array of dst points (x,y pairs)
+      * @param dstIndex The index of the first [x,y] pair of dst floats
+      * @param src   The array of src points (x,y pairs)
+      * @param srcIndex The index of the first [x,y] pair of src floats
+      * @param pointCount The number of points (x,y pairs) to transform
+      */
+
+     private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
+                           int pointCount) {
+         //checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
+
+         float[] tmpDest = dst;
+         boolean inPlace = dst == src;
+         if (inPlace) {
+             tmpDest = new float[dstIndex + pointCount * 2];
+         }
+
+         for (int i = 0 ; i < pointCount ; i++) {
+             // just in case we are doing in place, we better put this in temp vars
+             float x = mValues[0] * src[i + srcIndex] +
+                       mValues[1] * src[i + srcIndex + 1] +
+                       mValues[2];
+             float y = mValues[3] * src[i + srcIndex] +
+                       mValues[4] * src[i + srcIndex + 1] +
+                       mValues[5];
+
+             tmpDest[i + dstIndex]     = x;
+             tmpDest[i + dstIndex + 1] = y;
+         }
+
+         if (inPlace) {
+             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, pointCount * 2);
+         }
+     }
+
+     /**
+      * Apply this matrix to the array of 2D points, and write the transformed
+      * points back into the array
+      *
+      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
+      */
+
+     private void mapPoints(float[] pts) {
+         mapPoints(pts, 0, pts, 0, pts.length >> 1);
+     }
+
+    /**
+     * multiply two matrices and store them in a 3rd.
+     * <p/>This in effect does dest = a*b
+     * dest cannot be the same as a or b.
+     */
+    private static void multiply(float dest[], float[] a, float[] b) {
+        // first row
+        dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
+        dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
+        dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
+
+        // 2nd row
+        dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
+        dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
+        dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
+
+        // 3rd row
+        dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
+        dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
+        dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
+    }
+
+    /**
+     * Returns a matrix that represents a given translate
+     * @param dx
+     * @param dy
+     * @return
+     */
+    private static float[] getTranslate(float dx, float dy) {
+        return setTranslate(new float[9], dx, dy);
+    }
+
+    private static float[] setTranslate(float[] dest, float dx, float dy) {
+        dest[0] = 1;
+        dest[1] = 0;
+        dest[2] = dx;
+        dest[3] = 0;
+        dest[4] = 1;
+        dest[5] = dy;
+        dest[6] = 0;
+        dest[7] = 0;
+        dest[8] = 1;
+        return dest;
+    }
+
+    private static float[] getScale(float sx, float sy) {
+        return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
+    }
+
+    /**
+     * Returns a matrix that represents the given scale info.
+     * @param sx
+     * @param sy
+     * @param px
+     * @param py
+     */
+    private static float[] getScale(float sx, float sy, float px, float py) {
+        float[] tmp = new float[9];
+        float[] tmp2 = new float[9];
+
+        // TODO: do it in one pass
+
+        // translate tmp so that the pivot is in 0,0
+        setTranslate(tmp, -px, -py);
+
+        // scale into tmp2
+        multiply(tmp2, tmp, getScale(sx, sy));
+
+        // translate back the pivot back into tmp
+        multiply(tmp, tmp2, getTranslate(px, py));
+
+        return tmp;
+    }
+
+
+    private static float[] getRotate(float degrees) {
+        double rad = Math.toRadians(degrees);
+        float sin = (float)Math.sin(rad);
+        float cos = (float)Math.cos(rad);
+
+        return getRotate(sin, cos);
+    }
+
+    private static float[] getRotate(float sin, float cos) {
+        return setRotate(new float[9], sin, cos);
+    }
+
+    private static float[] setRotate(float[] dest, float degrees) {
+        double rad = Math.toRadians(degrees);
+        float sin = (float)Math.sin(rad);
+        float cos = (float)Math.cos(rad);
+
+        return setRotate(dest, sin, cos);
+    }
+
+    private static float[] setRotate(float[] dest, float sin, float cos) {
+        dest[0] = cos;
+        dest[1] = -sin;
+        dest[2] = 0;
+        dest[3] = sin;
+        dest[4] = cos;
+        dest[5] = 0;
+        dest[6] = 0;
+        dest[7] = 0;
+        dest[8] = 1;
+        return dest;
+    }
+
+    private static float[] getRotate(float degrees, float px, float py) {
+        float[] tmp = new float[9];
+        float[] tmp2 = new float[9];
+
+        // TODO: do it in one pass
+
+        // translate so that the pivot is in 0,0
+        setTranslate(tmp, -px, -py);
+
+        // rotate into tmp2
+        double rad = Math.toRadians(degrees);
+        float cos = (float)Math.cos(rad);
+        float sin = (float)Math.sin(rad);
+        multiply(tmp2, tmp, getRotate(sin, cos));
+
+        // translate back the pivot back into tmp
+        multiply(tmp, tmp2, getTranslate(px, py));
+
+        return tmp;
+    }
+
+    private static float[] getSkew(float kx, float ky) {
+        return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
+    }
+
+    private static float[] getSkew(float kx, float ky, float px, float py) {
+        float[] tmp = new float[9];
+        float[] tmp2 = new float[9];
+
+        // TODO: do it in one pass
+
+        // translate so that the pivot is in 0,0
+        setTranslate(tmp, -px, -py);
+
+        // skew into tmp2
+        multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
+        // translate back the pivot back into tmp
+        multiply(tmp, tmp2, getTranslate(px, py));
+
+        return tmp;
+    }
+
+
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint.java b/tools/layoutlib/bridge/src/android/graphics/Paint.java
index d13b5fe..2de21c1 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint.java
@@ -249,7 +249,7 @@
     private void updateFontObject() {
         if (mTypeface != null) {
             // Get the fonts from the TypeFace object.
-            List<Font> fonts = mTypeface.getFonts();
+            List<Font> fonts = Typeface_Delegate.getFonts(mTypeface);
 
             // create new font objects as well as FontMetrics, based on the current text size
             // and skew info.
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path.java b/tools/layoutlib/bridge/src/android/graphics/Path.java
index 12d2cde..c0bc005 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path.java
@@ -31,13 +31,13 @@
  * text on a path.
  */
 public class Path {
-    
+
     private FillType mFillType = FillType.WINDING;
     private GeneralPath mPath = new GeneralPath();
-    
+
     private float mLastX = 0;
     private float mLastY = 0;
-    
+
     //---------- Custom methods ----------
 
     public Shape getAwtShape() {
@@ -60,7 +60,7 @@
     public Path(Path src) {
         mPath.append(src.mPath, false /* connect */);
     }
-    
+
     /**
      * Clear any lines and curves from the path, making it empty.
      * This does NOT change the fill-type setting.
@@ -92,7 +92,7 @@
         EVEN_ODD        (GeneralPath.WIND_EVEN_ODD, false),
         INVERSE_WINDING (GeneralPath.WIND_NON_ZERO, true),
         INVERSE_EVEN_ODD(GeneralPath.WIND_EVEN_ODD, true);
-        
+
         FillType(int rule, boolean inverse) {
             this.rule = rule;
             this.inverse = inverse;
@@ -101,7 +101,7 @@
         final int rule;
         final boolean inverse;
     }
-    
+
     /**
      * Return the path's fill type. This defines how "inside" is
      * computed. The default value is WINDING.
@@ -121,7 +121,7 @@
         mFillType = ft;
         mPath.setWindingRule(ft.rule);
     }
-    
+
     /**
      * Returns true if the filltype is one of the INVERSE variants
      *
@@ -130,7 +130,7 @@
     public boolean isInverseFillType() {
         return mFillType.inverse;
     }
-    
+
     /**
      * Toggles the INVERSE state of the filltype
      */
@@ -150,7 +150,7 @@
                 break;
         }
     }
-    
+
     /**
      * Returns true if the path is empty (contains no lines or curves)
      *
@@ -350,7 +350,7 @@
                       boolean forceMoveTo) {
         throw new UnsupportedOperationException();
     }
-    
+
     /**
      * Append the specified arc to the path as a new contour. If the start of
      * the path is different from the path's current last point, then an
@@ -365,7 +365,7 @@
     public void arcTo(RectF oval, float startAngle, float sweepAngle) {
         throw new UnsupportedOperationException();
     }
-    
+
     /**
      * Close the current contour. If the current point is not equal to the
      * first point of the contour, a line segment is automatically added.
@@ -383,13 +383,13 @@
         CW  (0),    // must match enum in SkPath.h
         /** counter-clockwise */
         CCW (1);    // must match enum in SkPath.h
-        
+
         Direction(int ni) {
             nativeInt = ni;
         }
         final int nativeInt;
     }
-    
+
     /**
      * Add a closed rectangle contour to the path
      *
@@ -400,7 +400,7 @@
         if (rect == null) {
             throw new NullPointerException("need rect parameter");
         }
-        
+
         addRect(rect.left, rect.top, rect.right, rect.bottom, dir);
     }
 
@@ -446,7 +446,7 @@
 
         // FIXME Need to support direction
         Ellipse2D ovalShape = new Ellipse2D.Float(oval.left, oval.top, oval.width(), oval.height());
-        
+
         mPath.append(ovalShape, false /* connect */);
     }
 
@@ -493,7 +493,7 @@
         // FIXME
         throw new UnsupportedOperationException();
     }
-    
+
     /**
      * Add a closed round-rectangle contour to the path. Each corner receives
      * two radius values [X, Y]. The corners are ordered top-left, top-right,
@@ -513,7 +513,7 @@
         // FIXME
         throw new UnsupportedOperationException();
     }
-    
+
     /**
      * Add a copy of src to the path, offset by (dx,dy)
      *
@@ -554,11 +554,11 @@
      */
     public void offset(float dx, float dy, Path dst) {
         GeneralPath newPath = new GeneralPath();
-        
+
         PathIterator iterator = mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy));
-        
+
         newPath.append(iterator, false /* connect */);
-        
+
         if (dst != null) {
             dst.mPath = newPath;
         } else {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface.java b/tools/layoutlib/bridge/src/android/graphics/Typeface.java
deleted file mode 100644
index af3adb5..0000000
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.FontLoader;
-
-import android.content.res.AssetManager;
-
-import java.awt.Font;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Re-implementation of Typeface over java.awt
- */
-public class Typeface {
-    private static final String DEFAULT_FAMILY = "sans-serif";
-    private static final int[] styleBuffer = new int[1];
-
-    /** The default NORMAL typeface object */
-    public static Typeface DEFAULT;
-    /**
-     * The default BOLD typeface object. Note: this may be not actually be
-     * bold, depending on what fonts are installed. Call getStyle() to know
-     * for sure.
-     */
-    public static Typeface DEFAULT_BOLD;
-    /** The NORMAL style of the default sans serif typeface. */
-    public static Typeface SANS_SERIF;
-    /** The NORMAL style of the default serif typeface. */
-    public static Typeface SERIF;
-    /** The NORMAL style of the default monospace typeface. */
-    public static Typeface MONOSPACE;
-
-    private static Typeface[] sDefaults;
-    private static FontLoader mFontLoader;
-
-    private final int mStyle;
-    private final List<Font> mFonts;
-    private final String mFamily;
-
-    // Style
-    public static final int NORMAL = _Original_Typeface.NORMAL;
-    public static final int BOLD = _Original_Typeface.BOLD;
-    public static final int ITALIC = _Original_Typeface.ITALIC;
-    public static final int BOLD_ITALIC = _Original_Typeface.BOLD_ITALIC;
-
-    /**
-     * Returns the underlying {@link Font} objects. The first item in the list is the real
-     * font. Any other items are fallback fonts for characters not found in the first one.
-     */
-    public List<Font> getFonts() {
-        return mFonts;
-    }
-
-    /** Returns the typeface's intrinsic style attributes */
-    public int getStyle() {
-        return mStyle;
-    }
-
-    /** Returns true if getStyle() has the BOLD bit set. */
-    public final boolean isBold() {
-        return (getStyle() & BOLD) != 0;
-    }
-
-    /** Returns true if getStyle() has the ITALIC bit set. */
-    public final boolean isItalic() {
-        return (getStyle() & ITALIC) != 0;
-    }
-
-    /**
-     * Create a typeface object given a family name, and option style information.
-     * If null is passed for the name, then the "default" font will be chosen.
-     * The resulting typeface object can be queried (getStyle()) to discover what
-     * its "real" style characteristics are.
-     *
-     * @param familyName May be null. The name of the font family.
-     * @param style  The style (normal, bold, italic) of the typeface.
-     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
-     * @return The best matching typeface.
-     */
-    public static Typeface create(String familyName, int style) {
-        styleBuffer[0] = style;
-        Font font = mFontLoader.getFont(familyName, styleBuffer);
-        if (font != null) {
-            ArrayList<Font> list = new ArrayList<Font>();
-            list.add(font);
-            list.addAll(mFontLoader.getFallBackFonts());
-            return new Typeface(familyName, styleBuffer[0], list);
-        }
-
-        return null;
-    }
-
-    /**
-     * Create a typeface object that best matches the specified existing
-     * typeface and the specified Style. Use this call if you want to pick a new
-     * style from the same family of an existing typeface object. If family is
-     * null, this selects from the default font's family.
-     *
-     * @param family May be null. The name of the existing type face.
-     * @param style  The style (normal, bold, italic) of the typeface.
-     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
-     * @return The best matching typeface.
-     */
-    public static Typeface create(Typeface family, int style) {
-        styleBuffer[0] = style;
-        Font font = mFontLoader.getFont(family.mFamily, styleBuffer);
-        if (font != null) {
-            ArrayList<Font> list = new ArrayList<Font>();
-            list.add(font);
-            list.addAll(mFontLoader.getFallBackFonts());
-            return new Typeface(family.mFamily, styleBuffer[0], list);
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns one of the default typeface objects, based on the specified style
-     *
-     * @return the default typeface that corresponds to the style
-     */
-    public static Typeface defaultFromStyle(int style) {
-        return sDefaults[style];
-    }
-
-    /**
-     * Create a new typeface from the specified font data.
-     * @param mgr The application's asset manager
-     * @param path  The file name of the font data in the assets directory
-     * @return The new typeface.
-     */
-    public static Typeface createFromAsset(AssetManager mgr, String path) {
-        return null;
-        //return new Typeface(nativeCreateFromAsset(mgr, path));
-    }
-
-    // don't allow clients to call this directly
-    private Typeface(String family, int style, List<Font> fonts) {
-        mFamily = family;
-        mFonts = Collections.unmodifiableList(fonts);
-        mStyle = style;
-    }
-
-    public static void init(FontLoader fontLoader) {
-        mFontLoader = fontLoader;
-
-        DEFAULT = create(DEFAULT_FAMILY, NORMAL);
-        DEFAULT_BOLD = create(DEFAULT_FAMILY, BOLD);
-        SANS_SERIF = create("sans-serif", NORMAL);
-        SERIF = create("serif", NORMAL);
-        MONOSPACE = create("monospace", NORMAL);
-        sDefaults = new Typeface[] {
-                DEFAULT,
-                DEFAULT_BOLD,
-                create(DEFAULT_FAMILY, ITALIC),
-                create(DEFAULT_FAMILY, BOLD_ITALIC),
-        };
-
-        /*
-        DEFAULT         = create((String)null, 0);
-        DEFAULT_BOLD    = create((String)null, Typeface.BOLD);
-        SANS_SERIF      = create("sans-serif", 0);
-        SERIF           = create("serif", 0);
-        MONOSPACE       = create("monospace", 0);
-
-        sDefaults = new Typeface[] {
-            DEFAULT,
-            DEFAULT_BOLD,
-            create((String)null, Typeface.ITALIC),
-            create((String)null, Typeface.BOLD_ITALIC),
-        };*/
-    }
-}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
new file mode 100644
index 0000000..309d934
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.FontLoader;
+
+import android.content.res.AssetManager;
+
+import java.awt.Font;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Delegate implementing the native methods of android.graphics.Typeface
+ *
+ * Through the layoutlib_create tool, the original native methods of Typeface have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original Matrix class.
+ *
+ * @see DelegateManager
+ *
+ */
+public final class Typeface_Delegate {
+
+    // ---- delegate manager ----
+    private static final DelegateManager<Typeface_Delegate> sManager =
+            new DelegateManager<Typeface_Delegate>();
+
+    // ---- delegate helper data ----
+    private static final String DEFAULT_FAMILY = "sans-serif";
+    private static final int[] STYLE_BUFFER = new int[1];
+
+    private static FontLoader sFontLoader;
+    private static final List<Typeface_Delegate> sPostInitDelegate =
+            new ArrayList<Typeface_Delegate>();
+
+    // ---- delegate data ----
+
+    private final String mFamily;
+    private int mStyle;
+    private List<Font> mFonts;
+
+
+    // ---- Public Helper methods ----
+
+    public static synchronized void init(FontLoader fontLoader) {
+        sFontLoader = fontLoader;
+
+        for (Typeface_Delegate delegate : sPostInitDelegate) {
+            delegate.init();
+        }
+        sPostInitDelegate.clear();
+    }
+
+    public static List<Font> getFonts(Typeface typeface) {
+        Typeface_Delegate delegate = sManager.getDelegate(typeface.native_instance);
+        if (delegate == null) {
+            assert false;
+            return null;
+        }
+
+        return delegate.mFonts;
+    }
+
+
+    // ---- native methods ----
+
+    public static synchronized int nativeCreate(String familyName, int style) {
+        if (familyName == null) {
+            familyName = DEFAULT_FAMILY;
+        }
+
+        Typeface_Delegate newDelegate = new Typeface_Delegate(familyName, style);
+        if (sFontLoader != null) {
+            newDelegate.init();
+        } else {
+            // font loader has not been initialized yet, add the delegate to a list of delegates
+            // to init when the font loader is initialized.
+            // There won't be any rendering before this happens anyway.
+            sPostInitDelegate.add(newDelegate);
+        }
+
+        return sManager.addDelegate(newDelegate);
+    }
+
+    public static synchronized int nativeCreateFromTypeface(int native_instance, int style) {
+        Typeface_Delegate delegate = sManager.getDelegate(native_instance);
+        if (delegate == null) {
+            assert false;
+            return 0;
+        }
+
+        Typeface_Delegate newDelegate = new Typeface_Delegate(delegate.mFamily, style);
+        if (sFontLoader != null) {
+            newDelegate.init();
+        } else {
+            // font loader has not been initialized yet, add the delegate to a list of delegates
+            // to init when the font loader is initialized.
+            // There won't be any rendering before this happens anyway.
+            sPostInitDelegate.add(newDelegate);
+        }
+
+        return sManager.addDelegate(newDelegate);
+    }
+
+    public static synchronized int nativeCreateFromAsset(AssetManager mgr, String path) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    public static synchronized int nativeCreateFromFile(String path) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    public static void nativeUnref(int native_instance) {
+        sManager.removeDelegate(native_instance);
+    }
+
+    public static int nativeGetStyle(int native_instance) {
+        Typeface_Delegate delegate = sManager.getDelegate(native_instance);
+        if (delegate == null) {
+            assert false;
+            return 0;
+        }
+
+        return delegate.mStyle;
+    }
+
+    public static void setGammaForText(float blackGamma, float whiteGamma) {
+        // This is for device testing only: pass
+    }
+
+    // ---- Private delegate/helper methods ----
+
+    private Typeface_Delegate(String family, int style) {
+        mFamily = family;
+        mStyle = style;
+    }
+
+    private void init() {
+        STYLE_BUFFER[0] = mStyle;
+        Font font = sFontLoader.getFont(mFamily, STYLE_BUFFER);
+        if (font != null) {
+            List<Font> list = new ArrayList<Font>();
+            list.add(font);
+            list.addAll(sFontLoader.getFallBackFonts());
+            mFonts = Collections.unmodifiableList(list);
+            mStyle = STYLE_BUFFER[0];
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index eb0eba2..9eb83c8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -31,13 +31,12 @@
 import com.android.tools.layoutlib.create.OverrideMethod;
 
 import android.content.ClipData;
-import android.content.ClipDescription;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.graphics.Typeface;
+import android.graphics.Typeface_Delegate;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
@@ -49,9 +48,9 @@
 import android.util.TypedValue;
 import android.view.BridgeInflater;
 import android.view.DragEvent;
-import android.view.InputChannel;
 import android.view.IWindow;
 import android.view.IWindowSession;
+import android.view.InputChannel;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.Surface;
@@ -220,7 +219,7 @@
         // load the fonts.
         FontLoader fontLoader = FontLoader.create(fontOsLocation);
         if (fontLoader != null) {
-            Typeface.init(fontLoader);
+            Typeface_Delegate.init(fontLoader);
         } else {
             return false;
         }
@@ -1007,7 +1006,7 @@
             // pass for now.
             return 0;
         }
-        
+
         @SuppressWarnings("unused")
         public void finishDrawing(IWindow arg0) throws RemoteException {
             // pass for now.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java
new file mode 100644
index 0000000..9d6dd27
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentValues;
+import android.content.IContentProvider;
+import android.content.OperationApplicationException;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.database.CursorWindow;
+import android.database.IBulkCursor;
+import android.database.IContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+
+/**
+ * Mock implementation of {@link IContentProvider}.
+ *
+ * TODO: never return null when the method is not supposed to. Return fake data instead.
+ */
+public final class BridgeContentProvider implements IContentProvider {
+
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> arg0)
+            throws RemoteException, OperationApplicationException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int bulkInsert(Uri arg0, ContentValues[] arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public IBulkCursor bulkQuery(Uri arg0, String[] arg1, String arg2, String[] arg3,
+            String arg4, IContentObserver arg5, CursorWindow arg6) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Bundle call(String arg0, String arg1, Bundle arg2) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int delete(Uri arg0, String arg1, String[] arg2) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public String getType(Uri arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Uri insert(Uri arg0, ContentValues arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public AssetFileDescriptor openAssetFile(Uri arg0, String arg1) throws RemoteException,
+            FileNotFoundException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public ParcelFileDescriptor openFile(Uri arg0, String arg1) throws RemoteException,
+            FileNotFoundException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3, String arg4)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public IBinder asBinder() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String[] getStreamTypes(Uri arg0, String arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public AssetFileDescriptor openTypedAssetFile(Uri arg0, String arg1, Bundle arg2)
+            throws RemoteException, FileNotFoundException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
index d89dba9..e15cb69 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
@@ -32,20 +32,28 @@
  */
 public class BridgeContentResolver extends ContentResolver {
 
+    private BridgeContentProvider mProvider = null;
+
     public BridgeContentResolver(Context context) {
         super(context);
     }
 
     @Override
     public IContentProvider acquireProvider(Context c, String name) {
-        // ignore
-        return null;
+        if (mProvider == null) {
+            mProvider = new BridgeContentProvider();
+        }
+
+        return mProvider;
     }
 
     @Override
     public IContentProvider acquireExistingProvider(Context c, String name) {
-        // ignore
-        return null;
+        if (mProvider == null) {
+            mProvider = new BridgeContentProvider();
+        }
+
+        return mProvider;
     }
 
     @Override
@@ -53,7 +61,7 @@
         // ignore
         return false;
     }
-    
+
     /**
      * Stub for the layoutlib bridge content resolver.
      */
@@ -62,7 +70,7 @@
             ContentObserver observer) {
         // pass
     }
-    
+
     /**
      * Stub for the layoutlib bridge content resolver.
      */
@@ -70,7 +78,7 @@
     public void unregisterContentObserver(ContentObserver observer) {
         // pass
     }
-    
+
     /**
      * Stub for the layoutlib bridge content resolver.
      */
@@ -78,7 +86,7 @@
     public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
         // pass
     }
-    
+
     /**
      * Stub for the layoutlib bridge content resolver.
      */
@@ -86,7 +94,7 @@
     public void startSync(Uri uri, Bundle extras) {
         // pass
     }
-    
+
     /**
      * Stub for the layoutlib bridge content resolver.
      */
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
index f501459..8592731 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
@@ -267,7 +267,7 @@
             customStyle = parser.getAttributeValue(null /* namespace*/, "style");
         }
         if (customStyle != null) {
-            IResourceValue item = findResValue(customStyle);
+            IResourceValue item = findResValue(customStyle, false /*forceFrameworkOnly*/);
 
             if (item instanceof IStyleResourceValue) {
                 defStyleValues = (IStyleResourceValue)item;
@@ -284,7 +284,7 @@
 
                 if (item != null) {
                     // item is a reference to a style entry. Search for it.
-                    item = findResValue(item.getValue());
+                    item = findResValue(item.getValue(), false /*forceFrameworkOnly*/);
 
                     if (item instanceof IStyleResourceValue) {
                         defStyleValues = (IStyleResourceValue)item;
@@ -414,7 +414,7 @@
         }
 
         // get the IResourceValue referenced by this value
-        IResourceValue resValue = findResValue(value);
+        IResourceValue resValue = findResValue(value, false /*forceFrameworkOnly*/);
 
         // if resValue is null, but value is not null, this means it was not a reference.
         // we return the name/value wrapper in a IResourceValue
@@ -450,7 +450,7 @@
         }
 
         // else attempt to find another IResourceValue referenced by this one.
-        IResourceValue resolvedValue = findResValue(value.getValue());
+        IResourceValue resolvedValue = findResValue(value.getValue(), value.isFramework());
 
         // if the value did not reference anything, then we simply return the input value
         if (resolvedValue == null) {
@@ -477,9 +477,11 @@
      * only support the android namespace.
      *
      * @param reference the resource reference to search for.
+     * @param forceFrameworkOnly if true all references are considered to be toward framework
+     *      resource even if the reference does not include the android: prefix.
      * @return a {@link IResourceValue} or <code>null</code>.
      */
-    IResourceValue findResValue(String reference) {
+    IResourceValue findResValue(String reference, boolean forceFrameworkOnly) {
         if (reference == null) {
             return null;
         }
@@ -561,7 +563,8 @@
                 segments[1] = segments[1].substring(BridgeConstants.PREFIX_ANDROID.length());
             }
 
-            return findResValue(segments[0], segments[1], frameworkOnly);
+            return findResValue(segments[0], segments[1],
+                    forceFrameworkOnly ? true :frameworkOnly);
         }
 
         // Looks like the value didn't reference anything. Return null.
@@ -998,8 +1001,7 @@
 
     @Override
     public ApplicationInfo getApplicationInfo() {
-        // TODO Auto-generated method stub
-        return null;
+        return new ApplicationInfo();
     }
 
     @Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlPullAttributes.java
index 4be6eabc..d145ff6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlPullAttributes.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlPullAttributes.java
@@ -41,7 +41,7 @@
     /*
      * (non-Javadoc)
      * @see android.util.XmlPullAttributes#getAttributeNameResource(int)
-     * 
+     *
      * This methods must return com.android.internal.R.attr.<name> matching
      * the name of the attribute.
      * It returns 0 if it doesn't find anything.
@@ -50,19 +50,19 @@
     public int getAttributeNameResource(int index) {
         // get the attribute name.
         String name = getAttributeName(index);
-        
+
         // get the attribute namespace
         String ns = mParser.getAttributeNamespace(index);
-        
+
         if (BridgeConstants.NS_RESOURCES.equals(ns)) {
             Integer v = Bridge.getResourceValue(BridgeConstants.RES_ATTR, name);
             if (v != null) {
                 return v.intValue();
             }
-            
+
             return 0;
         }
-        
+
         // this is not an attribute in the android namespace, we query the customviewloader, if
         // the namespaces match.
         if (mContext.getProjectCallback().getNamespace().equals(ns)) {
@@ -75,7 +75,7 @@
 
         return 0;
     }
-    
+
     /*
      * (non-Javadoc)
      * @see android.util.XmlPullAttributes#getAttributeResourceValue(int, int)
@@ -83,7 +83,7 @@
     @Override
     public int getAttributeResourceValue(int index, int defaultValue) {
         String value = getAttributeValue(index);
-        
+
         return resolveResourceValue(value, defaultValue);
     }
 
@@ -94,14 +94,15 @@
     @Override
     public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
         String value = getAttributeValue(namespace, attribute);
-        
+
         return resolveResourceValue(value, defaultValue);
     }
 
     private int resolveResourceValue(String value, int defaultValue) {
         // now look for this particular value
-        IResourceValue resource = mContext.resolveResValue(mContext.findResValue(value));
-        
+        IResourceValue resource = mContext.resolveResValue(
+                mContext.findResValue(value, mPlatformFile));
+
         if (resource != null) {
             Integer id = null;
             if (mPlatformFile || resource.isFramework()) {
@@ -115,7 +116,7 @@
                 return id;
             }
         }
-        
+
         return defaultValue;
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/DelegateManager.java
new file mode 100644
index 0000000..3d9f960
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/DelegateManager.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge;
+
+import android.util.SparseArray;
+
+/**
+ * Manages native delegates.
+ *
+ * This is used in conjunction with layoublib_create: certain Android java classes are mere
+ * wrappers around a heavily native based implementation, and we need a way to run these classes
+ * in our Eclipse rendering framework without bringing all the native code from the Android
+ * platform.
+ *
+ * Thus we instruct layoutlib_create to modify the bytecode of these classes to replace their
+ * native methods by "delegate calls".
+ *
+ * For example, a native method android.graphics.Matrix.init(...) will actually become
+ * a call to android.graphics.Matrix_Delegate.init(...).
+ *
+ * The Android java classes that use native code uses an int (Java side) to reference native
+ * objects. This int is generally directly the pointer to the C structure counterpart.
+ * Typically a creation method will return such an int, and then this int will be passed later
+ * to a Java method to identify the C object to manipulate.
+ *
+ * Since we cannot use the Java object reference as the int directly, DelegateManager manages the
+ * int -> Delegate class link.
+ *
+ * Native methods usually always have the int as parameters. The first thing the delegate method
+ * will do is call {@link #getDelegate(int)} to get the Java object matching the int.
+ *
+ * Typical native init methods are returning a new int back to the Java class, so
+ * {@link #addDelegate(Object)} does the same.
+ *
+ * @param <T> the delegate class to manage
+ */
+public final class DelegateManager<T> {
+
+    private final SparseArray<T> mDelegates = new SparseArray<T>();
+    private int mDelegateCounter = 0;
+
+    /**
+     * Returns the delegate from the given native int.
+     * @param native_object the native int.
+     * @return the delegate or null if not found.
+     */
+    public T getDelegate(int native_object) {
+        synchronized (mDelegates) {
+            return mDelegates.get(native_object);
+        }
+    }
+
+    /**
+     * Adds a delegate to the manager and returns the native int used to identify it.
+     * @param newDelegate the delegate to add
+     * @return a unique native int to identify the delegate
+     */
+    public int addDelegate(T newDelegate) {
+        synchronized (mDelegates) {
+            int native_object = ++mDelegateCounter;
+            mDelegates.put(native_object, newDelegate);
+            return native_object;
+        }
+    }
+
+    /**
+     * Removes the delegate matching the given native int.
+     * @param native_object the native int.
+     */
+    public void removeDelegate(int native_object) {
+        synchronized (mDelegates) {
+            mDelegates.remove(native_object);
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java
index 801503b..de89a81 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java
@@ -134,6 +134,15 @@
         return mFallBackFonts;
     }
 
+    /**
+     * Returns a {@link Font} object given a family name and a style value (constant in
+     * {@link Typeface}).
+     * @param family the family name
+     * @param style a 1-item array containing the requested style. Based on the font being read
+     *              the actual style may be different. The array contains the actual style after
+     *              the method returns.
+     * @return the font object or null if no match could be found.
+     */
     public synchronized Font getFont(String family, int[] style) {
         if (family == null) {
             return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java
index 3d0dd73..f624753 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java
@@ -148,8 +148,7 @@
                     parser.setInput(new FileReader(f));
 
                     d = Drawable.createFromXml(context.getResources(),
-                            // FIXME: we need to know if this resource is platform or not
-                            new BridgeXmlBlockParser(parser, context, false));
+                            new BridgeXmlBlockParser(parser, context, isFramework));
                     return d;
                 } catch (XmlPullParserException e) {
                     context.getLogger().error(e);
diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java
new file mode 100644
index 0000000..6eed8ba
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import com.android.tools.layoutlib.create.CreateInfo;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that native delegate classes implement all the required methods.
+ *
+ * This looks at {@link CreateInfo#DELEGATE_CLASS_NATIVES} to get the list of classes that
+ * have their native methods reimplemented through a delegate.
+ *
+ * Since the reimplemented methods are not native anymore, we look for the annotation
+ * {@link LayoutlibDelegate}, and look for a matching method in the delegate (named the same
+ * as the modified class with _Delegate added as a suffix).
+ * If the original native method is not static, then we make sure the delegate method also
+ * include the original class as first parameter (to access "this").
+ *
+ */
+public class TestNativeDelegate extends TestCase {
+
+    public void  testNativeDelegates() {
+
+        final String[] classes = CreateInfo.DELEGATE_CLASS_NATIVES;
+        final int count = classes.length;
+        for (int i = 0 ; i < count ; i++) {
+            loadAndCompareClasses(classes[i], classes[i] + "_Delegate");
+        }
+    }
+
+    private void loadAndCompareClasses(String originalClassName, String delegateClassName) {
+        // load the classes
+        try {
+            ClassLoader classLoader = TestNativeDelegate.class.getClassLoader();
+            Class<?> originalClass = classLoader.loadClass(originalClassName);
+            Class<?> delegateClass = classLoader.loadClass(delegateClassName);
+
+            compare(originalClass, delegateClass);
+        } catch (ClassNotFoundException e) {
+           fail("Failed to load class: " + e.getMessage());
+        } catch (SecurityException e) {
+            fail("Failed to load class: " + e.getMessage());
+        }
+    }
+
+    private void compare(Class<?> originalClass, Class<?> delegateClass) throws SecurityException {
+        Method[] originalMethods = originalClass.getDeclaredMethods();
+
+        for (Method originalMethod : originalMethods) {
+            // look for methods that were native: they have the LayoutlibDelegate annotation
+            if (originalMethod.getAnnotation(LayoutlibDelegate.class) == null) {
+                continue;
+            }
+
+            // get the signature.
+            Class<?>[] parameters = originalMethod.getParameterTypes();
+
+            // if the method is not static, then the class is added as the first parameter
+            // (for "this")
+            if ((originalMethod.getModifiers() & Modifier.STATIC) == 0) {
+
+                Class<?>[] newParameters = new Class<?>[parameters.length + 1];
+                newParameters[0] = originalClass;
+                System.arraycopy(parameters, 0, newParameters, 1, parameters.length);
+                parameters = newParameters;
+            }
+
+            try {
+                // try to load the method with the given parameter types.
+                delegateClass.getMethod(originalMethod.getName(), parameters);
+            } catch (NoSuchMethodException e) {
+                // compute a full class name that's long but not too long.
+                StringBuilder sb = new StringBuilder(originalMethod.getName() + "(");
+                for (int j = 0; j < parameters.length; j++) {
+                    Class<?> theClass = parameters[j];
+                    sb.append(theClass.getName());
+                    int dimensions = 0;
+                    while (theClass.isArray()) {
+                        dimensions++;
+                        theClass = theClass.getComponentType();
+                    }
+                    for (int i = 0; i < dimensions; i++) {
+                        sb.append("[]");
+                    }
+                    if (j < (parameters.length - 1)) {
+                        sb.append(",");
+                    }
+                }
+                sb.append(")");
+
+                fail(String.format("Missing %1$s.%2$s", delegateClass.getName(), sb.toString()));
+            }
+        }
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 92892784..f6d11fe 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -16,6 +16,8 @@
 
 package com.android.tools.layoutlib.create;
 
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
 /**
  * Describes the work to be done by {@link AsmGenerator}.
  */
@@ -83,7 +85,9 @@
             OverrideMethod.class,
             MethodListener.class,
             MethodAdapter.class,
-            CreateInfo.class
+            ICreateInfo.class,
+            CreateInfo.class,
+            LayoutlibDelegate.class
         };
 
     /**
@@ -99,8 +103,8 @@
      * The list of classes on which to delegate all native methods.
      */
     private final static String[] DELEGATE_CLASS_NATIVES = new String[] {
-        // TODO: comment out once DelegateClass is working
-        // "android.graphics.Paint"
+        "android.graphics.Matrix",
+        "android.graphics.Typeface",
     };
 
     /**
@@ -126,14 +130,12 @@
             "android.graphics.ComposeShader",       "android.graphics._Original_ComposeShader",
             "android.graphics.DashPathEffect",       "android.graphics._Original_DashPathEffect",
             "android.graphics.LinearGradient",      "android.graphics._Original_LinearGradient",
-            "android.graphics.Matrix",              "android.graphics._Original_Matrix",
             "android.graphics.Paint",               "android.graphics._Original_Paint",
             "android.graphics.Path",                "android.graphics._Original_Path",
             "android.graphics.PorterDuffXfermode",  "android.graphics._Original_PorterDuffXfermode",
             "android.graphics.RadialGradient",      "android.graphics._Original_RadialGradient",
             "android.graphics.Shader",              "android.graphics._Original_Shader",
             "android.graphics.SweepGradient",       "android.graphics._Original_SweepGradient",
-            "android.graphics.Typeface",            "android.graphics._Original_Typeface",
             "android.os.ServiceManager",            "android.os._Original_ServiceManager",
             "android.util.FloatMath",               "android.util._Original_FloatMath",
             "android.view.SurfaceView",             "android.view._Original_SurfaceView",
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index 4adaff9..43f2971 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -83,6 +83,7 @@
                         "com.android.internal.R**",
                         "android.pim.*", // for datepicker
                         "android.os.*",  // for android.os.Handler
+                        "android.database.ContentObserver", // for Digital clock
                         });
             aa.analyze();
             agen.generate();
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index 0179748..f275e39 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -37,20 +37,19 @@
 import java.util.Map;
 
 /**
- * Class that handles an Internet audio call over SIP. {@link SipManager}
- * facilitates instantiating a {@code SipAudioCall} object for making/receiving
- * calls. See {@link SipManager#makeAudioCall} and
- * {@link SipManager#takeAudioCall}.
+ * Handles an Internet audio call over SIP. You can instantiate this class with {@link SipManager},
+ * using {@link SipManager#makeAudioCall makeAudioCall()} and  {@link SipManager#takeAudioCall
+ * takeAudioCall()}.
  *
- * <p>Requires permissions to use this class:
+ * <p class="note"><strong>Note:</strong> Using this class require the
  *   {@link android.Manifest.permission#INTERNET} and
- *   {@link android.Manifest.permission#USE_SIP}.
- * <br/>Requires permissions to {@link #startAudio}:
+ *   {@link android.Manifest.permission#USE_SIP} permissions.<br/><br/>In addition, {@link
+ *   #startAudio} requires the
  *   {@link android.Manifest.permission#RECORD_AUDIO},
- *   {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
- *   {@link android.Manifest.permission#WAKE_LOCK}.
- * <br/>Requires permissions to {@link #setSpeakerMode}:
- *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
+ *   {@link android.Manifest.permission#ACCESS_WIFI_STATE}, and
+ *   {@link android.Manifest.permission#WAKE_LOCK} permissions; and {@link #setSpeakerMode
+ *   setSpeakerMode()} requires the
+ *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS} permission.</p>
  */
 public class SipAudioCall {
     private static final String TAG = SipAudioCall.class.getSimpleName();
@@ -58,7 +57,10 @@
     private static final boolean DONT_RELEASE_SOCKET = false;
     private static final int SESSION_TIMEOUT = 5; // in seconds
 
-    /** Listener class for all event callbacks. */
+    /** Listener for events relating to a SIP call, such as when a call is being
+     * recieved ("on ringing") or a call is outgoing ("on calling").
+     * <p>Many of these events are also received by {@link SipSession.Listener}.</p>
+     */
     public static class Listener {
         /**
          * Called when the call object is ready to make another call.
@@ -199,7 +201,7 @@
 
     /**
      * Sets the listener to listen to the audio call events. The method calls
-     * {@code setListener(listener, false)}.
+     * {@link #setListener setListener(listener, false)}.
      *
      * @param listener to listen to the audio call events of this object
      * @see #setListener(Listener, boolean)
@@ -537,14 +539,14 @@
     /**
      * Initiates an audio call to the specified profile. The attempt will be
      * timed out if the call is not established within {@code timeout} seconds
-     * and {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
+     * and {@link Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
      * will be called.
      *
      * @param peerProfile the SIP profile to make the call to
      * @param sipSession the {@link SipSession} for carrying out the call
      * @param timeout the timeout value in seconds. Default value (defined by
      *        SIP protocol) is used if {@code timeout} is zero or negative.
-     * @see Listener.onError
+     * @see Listener#onError
      * @throws SipException if the SIP service fails to create a session for the
      *        call
      */
@@ -582,12 +584,12 @@
      * Puts a call on hold.  When succeeds, {@link Listener#onCallHeld} is
      * called. The attempt will be timed out if the call is not established
      * within {@code timeout} seconds and
-     * {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
+     * {@link Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
      * will be called.
      *
      * @param timeout the timeout value in seconds. Default value (defined by
      *        SIP protocol) is used if {@code timeout} is zero or negative.
-     * @see Listener.onError
+     * @see Listener#onError
      * @throws SipException if the SIP service fails to hold the call
      */
     public void holdCall(int timeout) throws SipException {
@@ -604,12 +606,12 @@
     /**
      * Answers a call. The attempt will be timed out if the call is not
      * established within {@code timeout} seconds and
-     * {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
+     * {@link Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
      * will be called.
      *
      * @param timeout the timeout value in seconds. Default value (defined by
      *        SIP protocol) is used if {@code timeout} is zero or negative.
-     * @see Listener.onError
+     * @see Listener#onError
      * @throws SipException if the SIP service fails to answer the call
      */
     public void answerCall(int timeout) throws SipException {
@@ -628,12 +630,12 @@
      * Continues a call that's on hold. When succeeds,
      * {@link Listener#onCallEstablished} is called. The attempt will be timed
      * out if the call is not established within {@code timeout} seconds and
-     * {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
+     * {@link Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
      * will be called.
      *
      * @param timeout the timeout value in seconds. Default value (defined by
      *        SIP protocol) is used if {@code timeout} is zero or negative.
-     * @see Listener.onError
+     * @see Listener#onError
      * @throws SipException if the SIP service fails to unhold the call
      */
     public void continueCall(int timeout) throws SipException {
@@ -788,8 +790,8 @@
 
     /**
      * Puts the device to speaker mode.
-     * <p>Requires permission:
-     *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
+     * <p class="note"><strong>Note:</strong> Requires the
+     *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS} permission.</p>
      */
     public void setSpeakerMode(boolean speakerMode) {
         synchronized (this) {
@@ -799,20 +801,21 @@
     }
 
     /**
-     * Sends a DTMF code. According to RFC2833, event 0--9 maps to decimal
+     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2883</a>,
+     * event 0--9 maps to decimal
      * value 0--9, '*' to 10, '#' to 11, event 'A'--'D' to 12--15, and event
      * flash to 16. Currently, event flash is not supported.
      *
      * @param code the DTMF code to send. Value 0 to 15 (inclusive) are valid
      *        inputs.
-     * @see http://tools.ietf.org/html/rfc2833
      */
     public void sendDtmf(int code) {
         sendDtmf(code, null);
     }
 
     /**
-     * Sends a DTMF code. According to RFC2833, event 0--9 maps to decimal
+     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2883</a>,
+     * event 0--9 maps to decimal
      * value 0--9, '*' to 10, '#' to 11, event 'A'--'D' to 12--15, and event
      * flash to 16. Currently, event flash is not supported.
      *
@@ -890,10 +893,10 @@
     /**
      * Starts the audio for the established call. This method should be called
      * after {@link Listener#onCallEstablished} is called.
-     * <p>Requires permission:
+     * <p class="note"><strong>Note:</strong> Requires the
      *   {@link android.Manifest.permission#RECORD_AUDIO},
      *   {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
-     *   {@link android.Manifest.permission#WAKE_LOCK}.
+     *   {@link android.Manifest.permission#WAKE_LOCK} permissions.</p>
      */
     public void startAudio() {
         try {
diff --git a/voip/java/android/net/sip/SipErrorCode.java b/voip/java/android/net/sip/SipErrorCode.java
index 6aee5f1..509728f 100644
--- a/voip/java/android/net/sip/SipErrorCode.java
+++ b/voip/java/android/net/sip/SipErrorCode.java
@@ -17,11 +17,11 @@
 package android.net.sip;
 
 /**
- * Defines error code returned in
- * {@link SipRegistrationListener#onRegistrationFailed},
- * {@link SipSession.Listener#onError},
- * {@link SipSession.Listener#onCallChangeFailed} and
- * {@link SipSession.Listener#onRegistrationFailed}.
+ * Defines error codes returned during SIP actions. For example, during
+ * {@link SipRegistrationListener#onRegistrationFailed onRegistrationFailed()},
+ * {@link SipSession.Listener#onError onError()},
+ * {@link SipSession.Listener#onCallChangeFailed onCallChangeFailed()} and
+ * {@link SipSession.Listener#onRegistrationFailed onRegistrationFailed()}.
  */
 public class SipErrorCode {
     /** Not an error. */
diff --git a/voip/java/android/net/sip/SipException.java b/voip/java/android/net/sip/SipException.java
index 225b94f..0339395 100644
--- a/voip/java/android/net/sip/SipException.java
+++ b/voip/java/android/net/sip/SipException.java
@@ -17,7 +17,7 @@
 package android.net.sip;
 
 /**
- * General SIP-related exception class.
+ * Indicates a general SIP-related exception.
  */
 public class SipException extends Exception {
     public SipException() {
diff --git a/voip/java/android/net/sip/SipManager.java b/voip/java/android/net/sip/SipManager.java
index 38d2b0c..8aaa805 100644
--- a/voip/java/android/net/sip/SipManager.java
+++ b/voip/java/android/net/sip/SipManager.java
@@ -29,30 +29,29 @@
 import java.text.ParseException;
 
 /**
- * The class provides API for various SIP related tasks. Specifically, the API
- * allows an application to:
+ * Provides APIs for SIP tasks, such as initiating SIP connections, and provides access to related
+ * SIP services. This class is the starting point for any SIP actions. You can acquire an instance
+ * of it with {@link #newInstance newInstance()}.</p>
+ * <p>The APIs in this class allows you to:</p>
  * <ul>
- * <li>open a {@link SipProfile} to get ready for making outbound calls or have
- *      the background SIP service listen to incoming calls and broadcast them
- *      with registered command string. See
- *      {@link #open(SipProfile, PendingIntent, SipRegistrationListener)},
- *      {@link #open(SipProfile)}, {@link #close}, {@link #isOpened} and
- *      {@link #isRegistered}. It also facilitates handling of the incoming call
- *      broadcast intent. See
- *      {@link #isIncomingCallIntent}, {@link #getCallId},
- *      {@link #getOfferSessionDescription} and {@link #takeAudioCall}.</li>
- * <li>make/take SIP-based audio calls. See
- *      {@link #makeAudioCall} and {@link #takeAudioCall}.</li>
- * <li>register/unregister with a SIP service provider manually. See
- *      {@link #register} and {@link #unregister}.</li>
- * <li>process SIP events directly with a {@link SipSession} created by
- *      {@link #createSipSession}.</li>
+ * <li>Create a {@link SipSession} to get ready for making calls or listen for incoming calls. See
+ * {@link #createSipSession createSipSession()} and {@link #getSessionFor getSessionFor()}.</li>
+ * <li>Initiate and receive generic SIP calls or audio-only SIP calls. Generic SIP calls may
+ * be video, audio, or other, and are initiated with {@link #open open()}. Audio-only SIP calls
+ * should be handled with a {@link SipAudioCall}, which you can acquire with {@link
+ * #makeAudioCall makeAudioCall()} and {@link #takeAudioCall takeAudioCall()}.</li>
+ * <li>Register and unregister with a SIP service provider, with
+ *      {@link #register register()} and {@link #unregister unregister()}.</li>
+ * <li>Verify session connectivity, with {@link #isOpened isOpened()} and
+ *      {@link #isRegistered isRegistered()}.</li>
  * </ul>
- * {@code SipManager} can only be instantiated if SIP API is supported by the
- * device. (See {@link #isApiSupported}).
- * <p>Requires permissions to use this class:
- *   {@link android.Manifest.permission#INTERNET} and
- *   {@link android.Manifest.permission#USE_SIP}.
+ * <p class="note"><strong>Note:</strong> Not all Android-powered devices support VOIP calls using
+ * SIP. You should always call {@link android.net.sip.SipManager#isVoipSupported
+ * isVoipSupported()} to verify that the device supports VOIP calling and {@link
+ * android.net.sip.SipManager#isApiSupported isApiSupported()} to verify that the device supports
+ * the SIP APIs.<br/><br/>Your application must also request the {@link
+ * android.Manifest.permission#INTERNET} and {@link android.Manifest.permission#USE_SIP}
+ * permissions.</p>
  */
 public class SipManager {
     /**
@@ -160,7 +159,7 @@
     }
 
     /**
-     * Opens the profile for making calls. The caller may make subsequent calls
+     * Opens the profile for making generic SIP calls. The caller may make subsequent calls
      * through {@link #makeAudioCall}. If one also wants to receive calls on the
      * profile, use
      * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)}
@@ -179,7 +178,7 @@
     }
 
     /**
-     * Opens the profile for making calls and/or receiving calls. The caller may
+     * Opens the profile for making calls and/or receiving generic SIP calls. The caller may
      * make subsequent calls through {@link #makeAudioCall}. If the
      * auto-registration option is enabled in the profile, the SIP service
      * will register the profile to the corresponding SIP provider periodically
@@ -296,7 +295,7 @@
     /**
      * Creates a {@link SipAudioCall} to make a call. The attempt will be timed
      * out if the call is not established within {@code timeout} seconds and
-     * {@code SipAudioCall.Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
+     * {@link SipAudioCall.Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
      * will be called.
      *
      * @param localProfile the SIP profile to make the call from
@@ -307,7 +306,7 @@
      *        SIP protocol) is used if {@code timeout} is zero or negative.
      * @return a {@link SipAudioCall} object
      * @throws SipException if calling the SIP service results in an error
-     * @see SipAudioCall.Listener.onError
+     * @see SipAudioCall.Listener#onError
      */
     public SipAudioCall makeAudioCall(SipProfile localProfile,
             SipProfile peerProfile, SipAudioCall.Listener listener, int timeout)
@@ -327,7 +326,7 @@
      * Creates a {@link SipAudioCall} to make an audio call. The attempt will be
      * timed out if the call is not established within {@code timeout} seconds
      * and
-     * {@code SipAudioCall.Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
+     * {@link SipAudioCall.Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
      * will be called.
      *
      * @param localProfileUri URI of the SIP profile to make the call from
@@ -338,7 +337,7 @@
      *        SIP protocol) is used if {@code timeout} is zero or negative.
      * @return a {@link SipAudioCall} object
      * @throws SipException if calling the SIP service results in an error
-     * @see SipAudioCall.Listener.onError
+     * @see SipAudioCall.Listener#onError
      */
     public SipAudioCall makeAudioCall(String localProfileUri,
             String peerProfileUri, SipAudioCall.Listener listener, int timeout)
@@ -449,7 +448,7 @@
      * receiving calls.
      * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)} is
      * still needed to be called at least once in order for the SIP service to
-     * notify the caller with the {@code PendingIntent} when an incoming call is
+     * notify the caller with the {@link android.app.PendingIntent} when an incoming call is
      * received.
      *
      * @param localProfile the SIP profile to register with
diff --git a/voip/java/android/net/sip/SipProfile.java b/voip/java/android/net/sip/SipProfile.java
index dddb07d..6977e30 100644
--- a/voip/java/android/net/sip/SipProfile.java
+++ b/voip/java/android/net/sip/SipProfile.java
@@ -32,7 +32,10 @@
 import javax.sip.address.URI;
 
 /**
- * Class containing a SIP account, domain and server information.
+ * Defines a SIP profile, including a SIP account, domain and server information.
+ * <p>You can create a {@link SipProfile} using {@link
+ * SipProfile.Builder}. You can also retrieve one from a {@link SipSession}, using {@link
+ * SipSession#getLocalProfile} and {@link SipSession#getPeerProfile}.</p>
  */
 public class SipProfile implements Parcelable, Serializable, Cloneable {
     private static final long serialVersionUID = 1L;
@@ -59,7 +62,7 @@
             };
 
     /**
-     * Class to help create a {@code SipProfile}.
+     * Helper class for creating a {@link SipProfile}.
      */
     public static class Builder {
         private AddressFactory mAddressFactory;
diff --git a/voip/java/android/net/sip/SipRegistrationListener.java b/voip/java/android/net/sip/SipRegistrationListener.java
index e1f35ad..9968cc7 100644
--- a/voip/java/android/net/sip/SipRegistrationListener.java
+++ b/voip/java/android/net/sip/SipRegistrationListener.java
@@ -17,7 +17,7 @@
 package android.net.sip;
 
 /**
- * Listener class to listen to SIP registration events.
+ * Listener for SIP registration events.
  */
 public interface SipRegistrationListener {
     /**
diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java
index 9c08e46..5629b3c 100644
--- a/voip/java/android/net/sip/SipSession.java
+++ b/voip/java/android/net/sip/SipSession.java
@@ -20,14 +20,17 @@
 import android.util.Log;
 
 /**
- * A SIP session that is associated with a SIP dialog or a standalone
+ * Represents a SIP session that is associated with a SIP dialog or a standalone
  * transaction not within a dialog.
+ * <p>You can get a {@link SipSession} from {@link SipManager} with {@link
+ * SipManager#createSipSession createSipSession()} (when initiating calls) or {@link
+ * SipManager#getSessionFor getSessionFor()} (when receiving calls).</p>
  */
 public final class SipSession {
     private static final String TAG = "SipSession";
 
     /**
-     * Defines {@link SipSession} states.
+     * Defines SIP session states, such as "registering", "outgoing call", and "in call".
      */
     public static class State {
         /** When session is ready to initiate a call or transaction. */
@@ -98,7 +101,9 @@
     }
 
     /**
-     * Listener class that listens to {@link SipSession} events.
+     * Listener for events relating to a SIP session, such as when a session is being registered
+     * ("on registering") or a call is outgoing ("on calling").
+     * <p>Many of these events are also received by {@link SipAudioCall.Listener}.</p>
      */
     public static class Listener {
         /**
diff --git a/voip/java/android/net/sip/package.html b/voip/java/android/net/sip/package.html
new file mode 100644
index 0000000..790656b
--- /dev/null
+++ b/voip/java/android/net/sip/package.html
@@ -0,0 +1,39 @@
+<HTML>
+<BODY>
+<p>Provides access to Session Initiation Protocol (SIP) functionality, such as
+making and answering VOIP calls using SIP.</p>
+
+<p>To get started, you need to get an instance of the {@link android.net.sip.SipManager} by
+calling {@link android.net.sip.SipManager#newInstance newInstance()}.</p>
+
+<p>With the {@link android.net.sip.SipManager}, you can initiate SIP audio calls with {@link
+android.net.sip.SipManager#makeAudioCall makeAudioCall()} and {@link
+android.net.sip.SipManager#takeAudioCall takeAudioCall()}. Both methods require
+a {@link android.net.sip.SipAudioCall.Listener} that receives callbacks when the state of the
+call changes, such as when the call is ringing, established, or ended.</p>
+
+<p>Both {@link android.net.sip.SipManager#makeAudioCall makeAudioCall()} also requires two
+{@link android.net.sip.SipProfile} objects, representing the local device and the peer
+device. You can create a {@link android.net.sip.SipProfile} using the {@link
+android.net.sip.SipProfile.Builder} subclass.</p>
+
+<p>Once you have a {@link android.net.sip.SipAudioCall}, you can perform SIP audio call actions with
+the instance, such as make a call, answer a call, mute a call, turn on speaker mode, send DTMF
+tones, and more.</p>
+
+<p>If you want to create generic SIP connections (such as for video calls or other), you can
+create a SIP connection from the {@link android.net.sip.SipManager}, using {@link
+android.net.sip.SipManager#open open()}. If you only want to create audio SIP calls, though, you
+should use the {@link android.net.sip.SipAudioCall} class, as described above.</p>
+
+<p class="note"><strong>Note:</strong>
+Not all Android-powered devices support VOIP functionality with SIP. Before performing any SIP
+activity, you should call {@link android.net.sip.SipManager#isVoipSupported isVoipSupported()}
+to verify that the device supports VOIP calling and {@link
+android.net.sip.SipManager#isApiSupported isApiSupported()} to verify that the device supports the
+SIP APIs.<br/><br/>
+Your application must also request the {@link android.Manifest.permission#INTERNET} and {@link
+android.Manifest.permission#USE_SIP} permissions in order to use the SIP APIs.
+</p>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 84d615c..356a0bd 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -339,6 +339,16 @@
     public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
 
     /**
+     * In this Wi-Fi lock mode, Wi-Fi will behave as in the mode
+     * {@link #WIFI_MODE_FULL} but it operates at high performance
+     * at the expense of power. This mode should be used
+     * only when the wifi connection needs to have minimum loss and low
+     * latency as it can impact the battery life.
+     * @hide
+     */
+    public static final int WIFI_MODE_FULL_HIGH_PERF = 3;
+
+    /**
      * In this Wi-Fi lock mode, Wi-Fi will be kept active,
      * and will behave normally, i.e., it will attempt to automatically
      * establish a connection to a remembered access point that is
@@ -1261,8 +1271,8 @@
     /**
      * Creates a new WifiLock.
      *
-     * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL} and
-     * {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks.
+     * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL},
+     * and {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks.
      * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is 
      *            never shown to the user under normal conditions, but should be descriptive 
      *            enough to identify your application and the specific WifiLock within it, if it
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 313ae0b..3d8157c 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -161,6 +161,8 @@
 
     public native static String getDhcpError();
 
+    public native static boolean setSuspendOptimizationsCommand(boolean enabled);
+
     /**
      * Wait for the supplicant to send an event, returning the event string.
      * @return the event string sent by the supplicant.
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index faafb7a..6bd67cc 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -246,11 +246,20 @@
     private static final int CMD_RECONNECT                        = 75;
     /* Reassociate to a network */
     private static final int CMD_REASSOCIATE                      = 76;
-    /* Set power mode
-     * POWER_MODE_ACTIVE
-     * POWER_MODE_AUTO
+    /* Controls power mode and suspend mode optimizations
+     *
+     * When high perf mode is enabled, power mode is set to
+     * POWER_MODE_ACTIVE and suspend mode optimizations are disabled
+     *
+     * When high perf mode is disabled, power mode is set to
+     * POWER_MODE_AUTO and suspend mode optimizations are enabled
+     *
+     * Suspend mode optimizations include:
+     * - packet filtering
+     * - turn off roaming
+     * - DTIM wake up settings
      */
-    private static final int CMD_SET_POWER_MODE                   = 77;
+    private static final int CMD_SET_HIGH_PERF_MODE               = 77;
     /* Set bluetooth co-existence
      * BLUETOOTH_COEXISTENCE_MODE_ENABLED
      * BLUETOOTH_COEXISTENCE_MODE_DISABLED
@@ -335,8 +344,8 @@
      */
     private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
 
-    private static final int DRIVER_POWER_MODE_ACTIVE = 1;
-    private static final int DRIVER_POWER_MODE_AUTO = 0;
+    private static final int POWER_MODE_ACTIVE = 1;
+    private static final int POWER_MODE_AUTO = 0;
 
     /* Default parent state */
     private HierarchicalState mDefaultState = new DefaultState();
@@ -856,13 +865,13 @@
     }
 
     /**
-     * Set power mode
-     * @param mode
-     *     DRIVER_POWER_MODE_AUTO
-     *     DRIVER_POWER_MODE_ACTIVE
+     * Set high performance mode of operation.
+     * Enabling would set active power mode and disable suspend optimizations;
+     * disabling would set auto power mode and enable suspend optimizations
+     * @param enable true if enable, false otherwise
      */
-    public void setPowerMode(int mode) {
-        sendMessage(obtainMessage(CMD_SET_POWER_MODE, mode, 0));
+    public void setHighPerfModeEnabled(boolean enable) {
+        sendMessage(obtainMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0));
     }
 
     /**
@@ -1269,6 +1278,21 @@
         return null;
     }
 
+    private void setHighPerfModeEnabledNative(boolean enable) {
+        if(!WifiNative.setSuspendOptimizationsCommand(!enable)) {
+            Log.e(TAG, "set suspend optimizations failed!");
+        }
+        if (enable) {
+            if (!WifiNative.setPowerModeCommand(POWER_MODE_ACTIVE)) {
+                Log.e(TAG, "set power mode active failed!");
+            }
+        } else {
+            if (!WifiNative.setPowerModeCommand(POWER_MODE_AUTO)) {
+                Log.e(TAG, "set power mode auto failed!");
+            }
+        }
+    }
+
     private void configureLinkProperties() {
         if (WifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
             mLinkProperties = WifiConfigStore.getLinkProperties(mLastNetworkId);
@@ -1654,7 +1678,7 @@
                 case CMD_CLEAR_BLACKLIST:
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -1756,7 +1780,7 @@
                 case CMD_STOP_DRIVER:
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -1884,7 +1908,7 @@
                 case CMD_STOP_DRIVER:
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -1981,7 +2005,7 @@
                 case CMD_STOP_DRIVER:
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -2138,7 +2162,7 @@
                 case NETWORK_DISCONNECTION_EVENT:
                 case PASSWORD_MAY_BE_INCORRECT_EVENT:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -2192,8 +2216,8 @@
                         WifiNative.setScanModeCommand(false);
                     }
                     break;
-                case CMD_SET_POWER_MODE:
-                    WifiNative.setPowerModeCommand(message.arg1);
+                case CMD_SET_HIGH_PERF_MODE:
+                    setHighPerfModeEnabledNative(message.arg1 == 1);
                     break;
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                     WifiNative.setBluetoothCoexistenceModeCommand(message.arg1);
@@ -2256,7 +2280,7 @@
                 case CMD_START_DRIVER:
                 case CMD_STOP_DRIVER:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -2505,7 +2529,7 @@
             if (!mUseStaticIp) {
                 mDhcpThread = null;
                 mModifiedBluetoothCoexistenceMode = false;
-                mPowerMode = DRIVER_POWER_MODE_AUTO;
+                mPowerMode = POWER_MODE_AUTO;
 
                 if (shouldDisableCoexistenceMode()) {
                     /*
@@ -2535,10 +2559,10 @@
                 if (mPowerMode < 0) {
                   // Handle the case where supplicant driver does not support
                   // getPowerModeCommand.
-                    mPowerMode = DRIVER_POWER_MODE_AUTO;
+                    mPowerMode = POWER_MODE_AUTO;
                 }
-                if (mPowerMode != DRIVER_POWER_MODE_ACTIVE) {
-                    WifiNative.setPowerModeCommand(DRIVER_POWER_MODE_ACTIVE);
+                if (mPowerMode != POWER_MODE_ACTIVE) {
+                    WifiNative.setPowerModeCommand(POWER_MODE_ACTIVE);
                 }
 
                 Log.d(TAG, "DHCP request started");
@@ -2639,6 +2663,10 @@
               case CMD_RECONFIGURE_IP:
                   deferMessage(message);
                   break;
+                  /* Defer any power mode changes since we must keep active power mode at DHCP */
+              case CMD_SET_HIGH_PERF_MODE:
+                  deferMessage(message);
+                  break;
               default:
                 return NOT_HANDLED;
           }
@@ -2650,7 +2678,7 @@
       public void exit() {
           /* reset power state & bluetooth coexistence if on DHCP */
           if (!mUseStaticIp) {
-              if (mPowerMode != DRIVER_POWER_MODE_ACTIVE) {
+              if (mPowerMode != POWER_MODE_ACTIVE) {
                   WifiNative.setPowerModeCommand(mPowerMode);
               }