Merge "Doc change: Add time-lapse video to 3.0 highlights." into gingerbread
diff --git a/api/current.xml b/api/current.xml
index a78aa3a6..ad54650 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -101107,6 +101107,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<exception name="IOException" type="java.io.IOException">
+</exception>
 </method>
 <method name="connect"
  return="void"
@@ -101577,17 +101579,6 @@
  visibility="public"
 >
 </field>
-<field name="TYPE_OTHER"
- type="int"
- transient="false"
- volatile="false"
- value="-1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="TYPE_PLUS"
  type="int"
  transient="false"
@@ -101610,6 +101601,17 @@
  visibility="public"
 >
 </field>
+<field name="TYPE_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="MifareUltralight"
  extends="android.nfc.tech.BasicTagTechnology"
@@ -101643,7 +101645,7 @@
  visibility="public"
 >
 </method>
-<method name="readBlock"
+<method name="readPages"
  return="byte[]"
  abstract="false"
  native="false"
@@ -101653,7 +101655,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="page" type="int">
+<parameter name="pageOffset" type="int">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -101683,13 +101685,24 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="page" type="int">
+<parameter name="pageOffset" type="int">
 </parameter>
 <parameter name="data" type="byte[]">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<field name="PAGE_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TYPE_ULTRALIGHT"
  type="int"
  transient="false"
@@ -101716,7 +101729,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="10"
+ value="-1"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -102194,6 +102207,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="java.io.Closeable">
+</implements>
 <method name="close"
  return="void"
  abstract="true"
@@ -102204,6 +102219,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<exception name="IOException" type="java.io.IOException">
+</exception>
 </method>
 <method name="connect"
  return="void"
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index ffbd69d..b5596013 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -149,6 +149,11 @@
         ConnectivityManager mConnectivityManager;
         public void onReceive(Context context, Intent intent) {
             synchronized(this) {
+                // update state and roaming before we set the state - only state changes are
+                // noticed
+                TelephonyManager tm = TelephonyManager.getDefault();
+                setRoamingStatus(tm.isNetworkRoaming());
+                setSubtype(tm.getNetworkType(), tm.getNetworkTypeName());
                 if (intent.getAction().equals(TelephonyIntents.
                         ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
                     Phone.DataState state = getMobileDataState(intent);
@@ -254,9 +259,6 @@
                             reason == null ? "" : "(" + reason + ")");
                     setDetailedState(DetailedState.FAILED, reason, apnName);
                 }
-                TelephonyManager tm = TelephonyManager.getDefault();
-                setRoamingStatus(tm.isNetworkRoaming());
-                setSubtype(tm.getNetworkType(), tm.getNetworkTypeName());
             }
         }
     }
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index d340a99..039dfff 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -302,7 +302,7 @@
     public boolean isTeardownRequested() {
         return mTeardownRequested;
     }
-    
+
     /**
      * Send a  notification that the results of a scan for network access
      * points has completed, and results are available.
@@ -327,10 +327,10 @@
     }
 
     protected void setSubtype(int subtype, String subtypeName) {
-        if (mNetworkInfo.isConnected()) {
-            int oldSubtype = mNetworkInfo.getSubtype();
-            if (subtype != oldSubtype) {
-                mNetworkInfo.setSubtype(subtype, subtypeName);
+        int oldSubtype = mNetworkInfo.getSubtype();
+        if (subtype != oldSubtype) {
+            mNetworkInfo.setSubtype(subtype, subtypeName);
+            if (mNetworkInfo.isConnected()) {
                 Message msg = mTarget.obtainMessage(
                         EVENT_NETWORK_SUBTYPE_CHANGED, oldSubtype, 0, mNetworkInfo);
                 msg.sendToTarget();
diff --git a/core/java/android/nfc/tech/BasicTagTechnology.java b/core/java/android/nfc/tech/BasicTagTechnology.java
index e635f21..32a850d 100644
--- a/core/java/android/nfc/tech/BasicTagTechnology.java
+++ b/core/java/android/nfc/tech/BasicTagTechnology.java
@@ -117,7 +117,7 @@
     }
 
     @Override
-    public void close() {
+    public void close() throws IOException {
         try {
             /* Note that we don't want to physically disconnect the tag,
              * but just reconnect to it to reset its state
diff --git a/core/java/android/nfc/tech/IsoDep.java b/core/java/android/nfc/tech/IsoDep.java
index f6d141a..774982e 100644
--- a/core/java/android/nfc/tech/IsoDep.java
+++ b/core/java/android/nfc/tech/IsoDep.java
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public void close() {
+    public void close() throws IOException {
         try {
             mTag.getTagService().resetIsoDepTimeout();
         } catch (RemoteException e) {
diff --git a/core/java/android/nfc/tech/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java
index 34fd7cf..d337ead 100644
--- a/core/java/android/nfc/tech/MifareClassic.java
+++ b/core/java/android/nfc/tech/MifareClassic.java
@@ -55,14 +55,14 @@
     public static final byte[] KEY_NFC_FORUM =
             {(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7};
 
+    /** A Mifare Classic compatible card of unknown type */
+    public static final int TYPE_UNKNOWN = -1;
     /** A MIFARE Classic tag */
     public static final int TYPE_CLASSIC = 0;
     /** A MIFARE Plus tag */
     public static final int TYPE_PLUS = 1;
     /** A MIFARE Pro tag */
     public static final int TYPE_PRO = 2;
-    /** A Mifare Classic compatible card that does not match the other types */
-    public static final int TYPE_OTHER = -1;
 
     /** The tag contains 16 sectors, each holding 4 blocks. */
     public static final int SIZE_1K = 1024;
@@ -360,12 +360,6 @@
         transceive(cmd.array(), false);
     }
 
-    private void validateValueOperand(int value) {
-        if (value < 0) {
-            throw new IllegalArgumentException("value operand negative");
-        }
-    }
-
     /**
      * Copy from temporary memory to value block.
      * @param blockIndex
@@ -410,7 +404,7 @@
         return transceive(data, true);
     }
 
-    private void validateSector(int sector) {
+    private static void validateSector(int sector) {
         // Do not be too strict on upper bounds checking, since some cards
         // have more addressable memory than they report. For example,
         // Mifare Plus 2k cards will appear as Mifare Classic 1k cards when in
@@ -423,10 +417,16 @@
         }
     }
 
-    private void validateBlock(int block) {
+    private static void validateBlock(int block) {
         // Just looking for obvious out of bounds...
         if (block < 0 || block >= MAX_BLOCK_COUNT) {
             throw new IndexOutOfBoundsException("block out of bounds: " + block);
         }
     }
+
+    private static void validateValueOperand(int value) {
+        if (value < 0) {
+            throw new IllegalArgumentException("value operand negative");
+        }
+    }
 }
diff --git a/core/java/android/nfc/tech/MifareUltralight.java b/core/java/android/nfc/tech/MifareUltralight.java
index f096298..b514f1c 100644
--- a/core/java/android/nfc/tech/MifareUltralight.java
+++ b/core/java/android/nfc/tech/MifareUltralight.java
@@ -21,24 +21,43 @@
 
 import java.io.IOException;
 
+//TOOD: Ultralight C 3-DES authentication, one-way counter
+
 /**
  * Technology class representing MIFARE Ultralight and MIFARE Ultralight C tags.
  *
  * <p>Support for this technology type is optional. If the NFC stack doesn't support this technology
  * MIFARE Ultralight class tags will still be scanned, but will only show the NfcA technology.
  *
- * <p>MIFARE Ultralight class tags have a series of 4 bytes pages that can be individually written
- * and read in chunks of 4 for a total read of 16 bytes.
+ * <p>MIFARE Ultralight compatible tags have 4 byte pages. The read command
+ * returns 4 pages (16 bytes) at a time, for speed. The write command operates
+ * on a single page (4 bytes) to minimize EEPROM write cycles.
+ *
+ * <p>The original MIFARE Ultralight consists of a 64 byte EEPROM. The first
+ * 4 pages are for the OTP area, manufacturer data, and locking bits. They are
+ * readable and some bits are writable. The final 12 pages are the user
+ * read/write area. For more information see the NXP data sheet MF0ICU1.
+ *
+ * <p>The MIFARE Ultralight C consists of a 192 byte EEPROM. The first 4 pages
+ * are for OTP, manufacturer data, and locking bits. The next 36 pages are the
+ * user read/write area. The next 4 pages are additional locking bits, counters
+ * and authentication configuration and are readable. The final 4 pages are for
+ * the authentication key and are not readable. For more information see the
+ * NXP data sheet MF0ICU2.
  */
 public final class MifareUltralight extends BasicTagTechnology {
+    /** A MIFARE Ultralight compatible tag of unknown type */
+    public static final int TYPE_UNKNOWN = -1;
     /** A MIFARE Ultralight tag */
     public static final int TYPE_ULTRALIGHT = 1;
     /** A MIFARE Ultralight C tag */
     public static final int TYPE_ULTRALIGHT_C = 2;
-    /** The tag type is unknown */
-    public static final int TYPE_UNKNOWN = 10;
+
+    /** Size of a MIFARE Ultralight page in bytes */
+    public static final int PAGE_SIZE = 4;
 
     private static final int NXP_MANUFACTURER_ID = 0x04;
+    private static final int MAX_PAGE_COUNT = 256;
 
     private int mType;
 
@@ -68,48 +87,62 @@
 
         if (a.getSak() == 0x00 && tag.getId()[0] == NXP_MANUFACTURER_ID) {
             // could be UL or UL-C
+            //TODO: stack should use NXP AN1303 procedure to make a best guess
+            // attempt at classifying Ultralight vs Ultralight C.
             mType = TYPE_ULTRALIGHT;
         }
     }
 
-    /** Returns the type of the tag */
+    /** Returns the type of the tag.
+     * <p>It is very hard to always accurately classify a MIFARE Ultralight
+     * compatible tag as Ultralight original or Ultralight C. So consider
+     * {@link #getType} a hint. */
     public int getType() {
         return mType;
     }
 
     // Methods that require connect()
     /**
-     * Reads a single 16 byte block from the given page offset.
+     * Read 4 pages (16 bytes).
+     * <p>The MIFARE Ultralight protocol always reads 4 pages at a time.
+     * <p>If the read spans past the last readable block, then the tag will
+     * return pages that have been wrapped back to the first blocks. MIFARE
+     * Ultralight tags have readable blocks 0x00 through 0x0F. So a read to
+     * block offset 0x0E would return blocks 0x0E, 0x0F, 0x00, 0x01. MIFARE
+     * Ultralight C tags have readable blocks 0x00 through 0x2B. So a read to
+     * block 0x2A would return blocks 0x2A, 0x2B, 0x00, 0x01.
+     * <p>This requires that the tag be connected.
      *
-     * <p>This requires a that the tag be connected.
-     *
+     * @return 4 pages (16 bytes)
      * @throws IOException
      */
-    public byte[] readBlock(int page) throws IOException {
+    public byte[] readPages(int pageOffset) throws IOException {
+        validatePageOffset(pageOffset);
         checkConnected();
 
-        byte[] blockread_cmd = { 0x30, (byte) page}; // phHal_eMifareRead
-        return transceive(blockread_cmd, false);
+        byte[] cmd = { 0x30, (byte) pageOffset};
+        return transceive(cmd, false);
     }
 
     /**
-     * Writes a 4 byte page to the tag.
+     * Write 1 page (4 bytes).
+     * <p>The MIFARE Ultralight protocol always writes 1 page at a time.
+     * <p>This requires that the tag be connected.
      *
-     * <p>This requires a that the tag be connected.
-     *
-     * @param page The offset of the page to write
+     * @param pageOffset The offset of the page to write
      * @param data The data to write
      * @throws IOException
      */
-    public void writePage(int page, byte[] data) throws IOException {
+    public void writePage(int pageOffset, byte[] data) throws IOException {
+        validatePageOffset(pageOffset);
         checkConnected();
 
-        byte[] pagewrite_cmd = new byte[data.length + 2];
-        pagewrite_cmd[0] = (byte) 0xA2;
-        pagewrite_cmd[1] = (byte) page;
-        System.arraycopy(data, 0, pagewrite_cmd, 2, data.length);
+        byte[] cmd = new byte[data.length + 2];
+        cmd[0] = (byte) 0xA2;
+        cmd[1] = (byte) pageOffset;
+        System.arraycopy(data, 0, cmd, 2, data.length);
 
-        transceive(pagewrite_cmd, false);
+        transceive(cmd, false);
     }
 
     /**
@@ -127,4 +160,15 @@
     public byte[] transceive(byte[] data) throws IOException {
         return transceive(data, true);
     }
+
+    private static void validatePageOffset(int pageOffset) {
+        // Do not be too strict on upper bounds checking, since some cards
+        // may have more addressable memory than they report.
+        // Note that issuing a command to an out-of-bounds block is safe - the
+        // tag will wrap the read to an addressable area. This validation is a
+        // helper to guard against obvious programming mistakes.
+        if (pageOffset < 0 || pageOffset >= MAX_PAGE_COUNT) {
+            throw new IndexOutOfBoundsException("page out of bounds: " + pageOffset);
+        }
+    }
 }
diff --git a/core/java/android/nfc/tech/TagTechnology.java b/core/java/android/nfc/tech/TagTechnology.java
index aebb3e8..c8ccdcf 100644
--- a/core/java/android/nfc/tech/TagTechnology.java
+++ b/core/java/android/nfc/tech/TagTechnology.java
@@ -18,9 +18,10 @@
 
 import android.nfc.Tag;
 
+import java.io.Closeable;
 import java.io.IOException;
 
-public interface TagTechnology {
+public interface TagTechnology extends Closeable {
     /**
      * This technology is an instance of {@link NfcA}.
      * <p>Support for this technology type is mandatory.
@@ -135,5 +136,5 @@
      * @see #connect()
      * @see #reconnect()
      */
-    public void close();
+    public void close() throws IOException;
 }
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 046bb4e..504b828 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -727,8 +727,8 @@
     <string name="yes" msgid="5362982303337969312">"Aceptar"</string>
     <string name="no" msgid="5141531044935541497">"Cancelar"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Atención"</string>
-    <string name="capital_on" msgid="1544682755514494298">"Encendido"</string>
-    <string name="capital_off" msgid="6815870386972805832">"APAGADO"</string>
+    <string name="capital_on" msgid="1544682755514494298">"Sí"</string>
+    <string name="capital_off" msgid="6815870386972805832">"No"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Completar la acción mediante"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Utilizar de manera predeterminada en esta acción."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Borrar la predeterminación en Configuración de la página principal &gt; Aplicaciones &gt; Administrar aplicaciones."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 7485791..543b53e 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -450,7 +450,7 @@
     <item msgid="9192514806975898961">"Personalizar"</item>
   </string-array>
   <string-array name="emailAddressTypes">
-    <item msgid="8073994352956129127">"Personal"</item>
+    <item msgid="8073994352956129127">"Casa"</item>
     <item msgid="7084237356602625604">"Trabajo"</item>
     <item msgid="1112044410659011023">"Otra"</item>
     <item msgid="2374913952870110618">"Personalizar"</item>
@@ -558,7 +558,7 @@
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta el cargador"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Falta la tarjeta SIM"</string>
     <string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"No se ha insertado ninguna tarjeta SIM en el teléfono."</string>
-    <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inserta una tarjeta SIM."</string>
+    <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inserta una tarjeta SIM"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Solo llamadas de emergencia"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Bloqueada para la red"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La tarjeta SIM está bloqueada con el código PUK."</string>
@@ -727,8 +727,8 @@
     <string name="yes" msgid="5362982303337969312">"Aceptar"</string>
     <string name="no" msgid="5141531044935541497">"Cancelar"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Atención"</string>
-    <string name="capital_on" msgid="1544682755514494298">"Activado"</string>
-    <string name="capital_off" msgid="6815870386972805832">"Desconectado"</string>
+    <string name="capital_on" msgid="1544682755514494298">"SÍ"</string>
+    <string name="capital_off" msgid="6815870386972805832">"NO"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Completar acción utilizando"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Utilizar de forma predeterminada para esta acción"</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Borrar valores predeterminados en la página de configuración de la pantalla de inicio del teléfono &gt; Aplicaciones &gt; Administrar aplicaciones\"."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 9f3c8a8..8608b5b 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -589,7 +589,7 @@
     <string name="factorytest_not_system" msgid="4435201656767276723">"L\'azione FACTORY_TEST è supportata soltanto per i pacchetti installati in /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nessun pacchetto trovato che fornisca l\'azione FACTORY_TEST."</string>
     <string name="factorytest_reboot" msgid="6320168203050791643">"Riavvia"</string>
-    <string name="js_dialog_title" msgid="8143918455087008109">"La pagina all\'indirizzo <xliff:g id="TITLE">%s</xliff:g> indica:"</string>
+    <string name="js_dialog_title" msgid="8143918455087008109">"Avviso relativo alla pagina <xliff:g id="TITLE">%s</xliff:g>:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Uscire da questa pagina?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Seleziona OK per continuare o Annulla per rimanere nella pagina corrente."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Conferma"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 00ee365..3563cf8 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -883,7 +883,7 @@
     <string name="reset" msgid="2448168080964209908">"リセット"</string>
     <string name="submit" msgid="1602335572089911941">"送信"</string>
     <string name="description_star" msgid="2654319874908576133">"お気に入り"</string>
-    <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"運転モードを有効にする"</string>
+    <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"運転モードになっています"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"運転モードを終了するには選択してください。"</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"テザリングまたはアクセスポイントが有効です"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"タップして設定する"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 8de3d33..37f56ea 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -608,7 +608,7 @@
     <string name="save_password_never" msgid="8274330296785855105">"Никогда"</string>
     <string name="open_permission_deny" msgid="5661861460947222274">"У вас нет разрешения на открытие этой страницы."</string>
     <string name="text_copied" msgid="4985729524670131385">"Текст скопирован в буфер обмена."</string>
-    <string name="more_item_label" msgid="4650918923083320495">"Дополнительно"</string>
+    <string name="more_item_label" msgid="4650918923083320495">"Ещё"</string>
     <string name="prepend_shortcut_label" msgid="2572214461676015642">"Меню+"</string>
     <string name="menu_space_shortcut_label" msgid="2410328639272162537">"пробел"</string>
     <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"ввод"</string>
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index 62e27d3..78d2ccd 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -1,6 +1,6 @@
 page.title=ADT Plugin for Eclipse
 adt.zip.version=9.0.0
-adt.zip.download=ADT-9.0.0.zip
+adt.zip.download=ADT_9.0.0.zip
 adt.zip.bytes=4433536
 adt.zip.checksum=bc2757f2a5a11d131390ce547bae154b
 
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index 7d39e67..d188bc5 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -103,8 +103,10 @@
     <li>The LogCat view in DDMS now properly displays UTF-8 characters.</li>
     <li>The SDK Manager is more reliable on Windows. For details on the improvements, see the
     <a href="http://tools.android.com/recent/sdkmanagerfixes">Android Tools Project Site</a>. </li>
-    <li>If you enabled snapshots for an AVD, they are automatically captured. The emulator also now restores to the state when
-     it last closed almost instantly.</li>
+    <li>Early look at the new snapshot feature: To improve startup time for the emulator, you can
+enable snapshots for the system state. The emulator will then restore to the state when it last
+closed almost instantly. <strong>Note:</strong> The snapshot feature is still under active
+development and might not always perform as expected.</li>
     <li>Fixed the missing JAR file error that prevented <code>draw9patch</code> from running.</li>
     <li>Fixed the Windows launch scripts <code>hierarchyviewer</code> and <code>ddms</code> to support
     the new location of <code>adb</code>.</li>
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 0d0234b..2843ee6 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -254,26 +254,12 @@
         return false;
     }
 
-    if (value == "npt=now-" || value == "npt=0-") {
-        return false;
-    }
-
     if (strncmp(value.c_str(), "npt=", 4)) {
         return false;
     }
 
-    const char *s = value.c_str() + 4;
-    char *end;
-    double from = strtod(s, &end);
-
-    if (end == s || *end != '-') {
-        return false;
-    }
-
-    s = end + 1;
-    double to = strtod(s, &end);
-
-    if (end == s || *end != '\0' || to < from) {
+    float from, to;
+    if (!parseNTPRange(value.c_str() + 4, &from, &to)) {
         return false;
     }
 
@@ -307,5 +293,39 @@
     }
 }
 
+// static
+bool ASessionDescription::parseNTPRange(
+        const char *s, float *npt1, float *npt2) {
+    if (s[0] == '-') {
+        return false;  // no start time available.
+    }
+
+    if (!strncmp("now", s, 3)) {
+        return false;  // no absolute start time available
+    }
+
+    char *end;
+    *npt1 = strtof(s, &end);
+
+    if (end == s || *end != '-') {
+        // Failed to parse float or trailing "dash".
+        return false;
+    }
+
+    s = end + 1;  // skip the dash.
+
+    if (!strncmp("now", s, 3)) {
+        return false;  // no absolute end time available
+    }
+
+    *npt2 = strtof(s, &end);
+
+    if (end == s || *end != '\0') {
+        return false;
+    }
+
+    return *npt2 > *npt1;
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/rtsp/ASessionDescription.h b/media/libstagefright/rtsp/ASessionDescription.h
index a3fa79e..b462983 100644
--- a/media/libstagefright/rtsp/ASessionDescription.h
+++ b/media/libstagefright/rtsp/ASessionDescription.h
@@ -55,6 +55,14 @@
 
     bool findAttribute(size_t index, const char *key, AString *value) const;
 
+    // parses strings of the form
+    //   npt      := npt-time "-" npt-time? | "-" npt-time
+    //   npt-time := "now" | [0-9]+("." [0-9]*)?
+    //
+    // Returns true iff both "npt1" and "npt2" times were available,
+    // i.e. we have a fixed duration, otherwise this is live streaming.
+    static bool parseNTPRange(const char *s, float *npt1, float *npt2);
+
 protected:
     virtual ~ASessionDescription();
 
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 8f8e10a..5c6ff82 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -938,13 +938,11 @@
 
         AString val;
         CHECK(GetAttribute(range.c_str(), "npt", &val));
-        float npt1, npt2;
 
-        if (val == "now-" || val == "0-") {
+        float npt1, npt2;
+        if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
             // This is a live stream and therefore not seekable.
             return;
-        } else {
-            CHECK_EQ(sscanf(val.c_str(), "%f-%f", &npt1, &npt2), 2);
         }
 
         i = response->mHeaders.indexOfKey("rtp-info");
diff --git a/packages/SettingsProvider/res/values-fi/strings.xml b/packages/SettingsProvider/res/values-fi/strings.xml
index 83c7f66..e4130e7a 100644
--- a/packages/SettingsProvider/res/values-fi/strings.xml
+++ b/packages/SettingsProvider/res/values-fi/strings.xml
@@ -19,5 +19,5 @@
 
 <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="4567566098528588863">"Asetuksien tallennus"</string>
+    <!-- outdated translation 1595939146166335368 -->     <string name="app_label" msgid="4567566098528588863">"Asetuksien tallennus"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index b510981..6d636e1 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"UI systému"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"UI systému"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Vymazat"</string>
     <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>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 6b22329..d60cd04 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"System-UI"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"Systemets brugergrænseflade"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ryd"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen meddelelser"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"I gang"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a5a97c67..2155141 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"System-UI"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"System-UI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Löschen"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Keine Benachrichtigungen"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktuell"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 79b90f8..1f1b5a8 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"UI συστήματ."</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"UI συστήματος"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Εκκαθάριση"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Δεν υπάρχουν ειδοποιήσεις"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Εν εξελίξει"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 4a13f44..ff025cc 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"Sistema UI"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"Sistema UI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No hay notificaciones"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continuo"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 38c6f91..909a088 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"IU sistema"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"IU del sistema"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No tienes notificaciones"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Entrante"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index c5b6ce8..4efef06 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"IU système"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"IU système"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Effacer"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Aucune notification"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 8bc101c..3dda5481 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"UI sistema"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"UI sistema"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Cancella"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nessuna notifica"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"In corso"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b059e74..5de9d86 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"システムUI"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"システムUI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"通知を消去"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"通知なし"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"実行中"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index d325c02..69e9702 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"시스템 UI"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"시스템 UI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"지우기"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"알림 없음"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"진행 중"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index cb44ef4..2cd836c 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"Sys.gr.snitt"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"Systemgrensesnitt"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Fjern"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen varslinger"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktiviteter"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 79f18b4..80a1f1a 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"Systeem-UI"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"Systeem-UI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Wissen"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Geen meldingen"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Actief"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index ddc5c88..289463d 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"Interfejs"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"Interfejs użytkownika systemu"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Wyczyść"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Brak powiadomień"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Bieżące"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index e89346d0..6301e28 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"IU do sist."</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"IU do sistema"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Limpar"</string>
     <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>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 23e4870..755b85e 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"Interf sist"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"Interf sist"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Limpar"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 71109e3..94892ea 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"Графический интерфейс системы"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"Графический интерфейс системы"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Очистить"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Нет уведомлений"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текущие"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 492a74d..75a081d 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"Gränssnitt"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"Gränssnitt"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ta bort"</string>
     <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>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 504ea45..c63e489 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"Sist Arayüzü"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"Sistem Arayüzü"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Temizle"</string>
     <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>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 6e59024..131a4db 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"系统用户界面"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"系统用户界面"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"无通知"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"正在进行的"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 906a68c..75f2d3d 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 7164937344850004466 -->     <string name="app_label" msgid="4489004083283879149">"系統 UI"</string>
+    <!-- outdated translation 7290757281635988063 -->     <string name="app_label" msgid="4489004083283879149">"系統 UI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"沒有通知"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"進行中"</string>
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index b225e56..128d7bf 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -26,6 +26,7 @@
 import static android.os.BatteryManager.BATTERY_STATUS_FULL;
 import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
 import android.media.AudioManager;
+import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
@@ -70,12 +71,12 @@
 
     private boolean mKeyguardBypassEnabled;
 
-    private boolean mDevicePluggedIn;
-
     private boolean mDeviceProvisioned;
 
     private int mBatteryLevel;
 
+    private int mBatteryStatus;
+
     private CharSequence mTelephonyPlmn;
     private CharSequence mTelephonySpn;
 
@@ -203,7 +204,7 @@
 
         // take a guess to start
         mSimState = IccCard.State.READY;
-        mDevicePluggedIn = true;
+        mBatteryStatus = BATTERY_STATUS_FULL;
         mBatteryLevel = 100;
 
         mTelephonyPlmn = getDefaultPlmn();
@@ -283,13 +284,12 @@
     /**
      * Handle {@link #MSG_BATTERY_UPDATE}
      */
-    private void handleBatteryUpdate(int pluggedInStatus, int batteryLevel) {
+    private void handleBatteryUpdate(int batteryStatus, int batteryLevel) {
         if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
-        final boolean pluggedIn = isPluggedIn(pluggedInStatus);
-
-        if (isBatteryUpdateInteresting(pluggedIn, batteryLevel)) {
+        if (isBatteryUpdateInteresting(batteryStatus, batteryLevel)) {
+            mBatteryStatus = batteryStatus;
             mBatteryLevel = batteryLevel;
-            mDevicePluggedIn = pluggedIn;
+            final boolean pluggedIn = isPluggedIn(batteryStatus);;
             for (int i = 0; i < mInfoCallbacks.size(); i++) {
                 mInfoCallbacks.get(i).onRefreshBatteryInfo(
                         shouldShowBatteryInfo(), pluggedIn, batteryLevel);
@@ -336,26 +336,34 @@
         return status == BATTERY_STATUS_CHARGING || status == BATTERY_STATUS_FULL;
     }
 
-    private boolean isBatteryUpdateInteresting(boolean pluggedIn, int batteryLevel) {
+    private boolean isBatteryUpdateInteresting(int batteryStatus, int batteryLevel) {
         // change in plug is always interesting
-        if (mDevicePluggedIn != pluggedIn) {
+        final boolean isPluggedIn = isPluggedIn(batteryStatus);
+        final boolean wasPluggedIn = isPluggedIn(mBatteryStatus);
+        final boolean stateChangedWhilePluggedIn =
+            wasPluggedIn == true && isPluggedIn == true && (mBatteryStatus != batteryStatus);
+        if (wasPluggedIn != isPluggedIn || stateChangedWhilePluggedIn) {
             return true;
         }
 
         // change in battery level while plugged in
-        if (pluggedIn && mBatteryLevel != batteryLevel) {
+        if (isPluggedIn && mBatteryLevel != batteryLevel) {
             return true;
         }
 
-        if (!pluggedIn) {
+        if (!isPluggedIn) {
             // not plugged in and below threshold
-            if (batteryLevel < LOW_BATTERY_THRESHOLD && batteryLevel != mBatteryLevel) {
+            if (isBatteryLow(batteryLevel) && batteryLevel != mBatteryLevel) {
                 return true;
             }
         }
         return false;
     }
 
+    private boolean isBatteryLow(int batteryLevel) {
+        return batteryLevel < LOW_BATTERY_THRESHOLD;
+    }
+
     /**
      * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
      * @return The string to use for the plmn, or null if it should not be shown.
@@ -485,7 +493,12 @@
     }
 
     public boolean isDevicePluggedIn() {
-        return mDevicePluggedIn;
+        return isPluggedIn(mBatteryStatus);
+    }
+
+    public boolean isDeviceCharged() {
+        return mBatteryStatus == BatteryManager.BATTERY_STATUS_FULL
+                || mBatteryLevel >= 100; // in case a particular device doesn't flag it
     }
 
     public int getBatteryLevel() {
@@ -493,7 +506,7 @@
     }
 
     public boolean shouldShowBatteryInfo() {
-        return mDevicePluggedIn || mBatteryLevel < LOW_BATTERY_THRESHOLD;
+        return isPluggedIn(mBatteryStatus) || isBatteryLow(mBatteryLevel);
     }
 
     public CharSequence getTelephonyPlmn() {
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 5a20b93..85495dc 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -34,6 +34,7 @@
 import android.graphics.drawable.Drawable;
 import android.util.Log;
 import android.media.AudioManager;
+import android.os.BatteryManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
@@ -417,7 +418,7 @@
         }
 
         if (mPluggedIn) {
-            if (mBatteryLevel >= 100) {
+            if (mUpdateMonitor.isDeviceCharged()) {
                 mCharging = getContext().getString(R.string.lockscreen_charged);
             } else {
                 mCharging = getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel);
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index ffd0a47..fe274f2 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -296,7 +296,7 @@
         } else if (mShowingBatteryInfo && mNextAlarm == null) {
             // battery only
             if (mPluggedIn) {
-              if (mBatteryLevel >= 100) {
+              if (mUpdateMonitor.isDeviceCharged()) {
                 mStatus1.setText(getContext().getString(R.string.lockscreen_charged));
               } else {
                   mStatus1.setText(getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel));
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index 0da353a..4612af1 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -1806,7 +1806,8 @@
         AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
         AudioSystem::DEVICE_OUT_WIRED_HEADSET |
         AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) &&
-        (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) &&
+        ((getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) ||
+         (stream == AudioSystem::SYSTEM)) &&
         streamDesc.mCanBeMuted) {
         volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
         // when the phone is ringing we must consider that music could have been paused just before