Merge "Remove debug logging for b/106899184." into klp-dev
diff --git a/api/current.txt b/api/current.txt
index 973a9fdc..9a90a58 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18327,7 +18327,7 @@
     ctor public ParcelFileDescriptor(android.os.ParcelFileDescriptor);
     method public static android.os.ParcelFileDescriptor adoptFd(int);
     method public boolean canDetectErrors();
-    method public void checkError(boolean) throws java.io.IOException;
+    method public void checkError() throws java.io.IOException;
     method public void close() throws java.io.IOException;
     method public void closeWithError(java.lang.String) throws java.io.IOException;
     method public static android.os.ParcelFileDescriptor[] createPipe() throws java.io.IOException;
@@ -18366,8 +18366,12 @@
     ctor public ParcelFileDescriptor.AutoCloseOutputStream(android.os.ParcelFileDescriptor);
   }
 
+  public static class ParcelFileDescriptor.FileDescriptorDetachedException extends java.io.IOException {
+    ctor public ParcelFileDescriptor.FileDescriptorDetachedException();
+  }
+
   public static abstract interface ParcelFileDescriptor.OnCloseListener {
-    method public abstract void onClose(java.io.IOException, boolean);
+    method public abstract void onClose(java.io.IOException);
   }
 
   public class ParcelFormatException extends java.lang.RuntimeException {
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 5a49b98..e436241 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -80,7 +80,7 @@
     private byte[] mStatusBuf;
 
     /**
-     * Status read by {@link #checkError(boolean)}, or null if not read yet.
+     * Status read by {@link #checkError()}, or null if not read yet.
      */
     private Status mStatus;
 
@@ -371,7 +371,7 @@
      * <p>
      * The write end has the ability to deliver an error message through
      * {@link #closeWithError(String)} which can be handled by the read end
-     * calling {@link #checkError(boolean)}, usually after detecting an EOF.
+     * calling {@link #checkError()}, usually after detecting an EOF.
      * This can also be used to detect remote crashes.
      */
     public static ParcelFileDescriptor[] createReliablePipe() throws IOException {
@@ -409,7 +409,7 @@
      * <p>
      * Both ends have the ability to deliver an error message through
      * {@link #closeWithError(String)} which can be detected by the other end
-     * calling {@link #checkError(boolean)}, usually after detecting an EOF.
+     * calling {@link #checkError()}, usually after detecting an EOF.
      * This can also be used to detect remote crashes.
      */
     public static ParcelFileDescriptor[] createReliableSocketPair() throws IOException {
@@ -698,7 +698,7 @@
      * Indicates if this ParcelFileDescriptor can communicate and detect remote
      * errors/crashes.
      *
-     * @see #checkError(boolean)
+     * @see #checkError()
      */
     public boolean canDetectErrors() {
         if (mWrapped != null) {
@@ -716,17 +716,16 @@
      * If this ParcelFileDescriptor is unable to detect remote errors, it will
      * return silently.
      *
-     * @param throwIfDetached requests that an exception be thrown if the remote
-     *            side called {@link #detachFd()}. Once detached, the remote
+     * @throws IOException for normal errors.
+     * @throws FileDescriptorDetachedException
+     *            if the remote side called {@link #detachFd()}. Once detached, the remote
      *            side is unable to communicate any errors through
-     *            {@link #closeWithError(String)}. An application may pass true
-     *            if it needs a stronger guarantee that the stream was closed
-     *            normally and was not merely detached.
+     *            {@link #closeWithError(String)}.
      * @see #canDetectErrors()
      */
-    public void checkError(boolean throwIfDetached) throws IOException {
+    public void checkError() throws IOException {
         if (mWrapped != null) {
-            mWrapped.checkError(throwIfDetached);
+            mWrapped.checkError();
         } else {
             if (mStatus == null) {
                 if (mCommFd == null) {
@@ -739,8 +738,7 @@
                 mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer());
             }
 
-            if (mStatus == null || mStatus.status == Status.OK
-                    || (mStatus.status == Status.DETACHED && !throwIfDetached)) {
+            if (mStatus == null || mStatus.status == Status.OK) {
                 // No status yet, or everything is peachy!
                 return;
             } else {
@@ -885,13 +883,26 @@
          * attached has been closed.
          *
          * @param e error state, or {@code null} if closed cleanly.
-         * @param fromDetach indicates if close event was result of
-         *            {@link ParcelFileDescriptor#detachFd()}. After detach the
-         *            remote side may continue reading/writing to the underlying
-         *            {@link FileDescriptor}, but they can no longer deliver
-         *            reliable close/error events.
+         *        If the close event was the result of
+         *        {@link ParcelFileDescriptor#detachFd()}, this will be a
+         *        {@link FileDescriptorDetachedException}. After detach the
+         *        remote side may continue reading/writing to the underlying
+         *        {@link FileDescriptor}, but they can no longer deliver
+         *        reliable close/error events.
          */
-        public void onClose(IOException e, boolean fromDetach);
+        public void onClose(IOException e);
+    }
+
+    /**
+     * Exception that indicates that the file descriptor was detached.
+     */
+    public static class FileDescriptorDetachedException extends IOException {
+
+        private static final long serialVersionUID = 0xDe7ac4edFdL;
+
+        public FileDescriptorDetachedException() {
+            super("Remote side is detached");
+        }
     }
 
     /**
@@ -934,7 +945,7 @@
                 case ERROR:
                     return new IOException("Remote error: " + msg);
                 case DETACHED:
-                    return new IOException("Remote side is detached");
+                    return new FileDescriptorDetachedException();
                 case LEAKED:
                     return new IOException("Remote side was leaked");
                 default:
@@ -959,13 +970,7 @@
                 @Override
                 public void handleMessage(Message msg) {
                     final Status s = (Status) msg.obj;
-                    if (s.status == Status.DETACHED) {
-                        listener.onClose(null, true);
-                    } else if (s.status == Status.OK) {
-                        listener.onClose(null, false);
-                    } else {
-                        listener.onClose(s.asIOException(), false);
-                    }
+                    listener.onClose(s != null ? s.asIOException() : null);
                 }
             };
         }
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index e4956dd..c0fde2e 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1099,13 +1099,18 @@
     }
 
     @Override
-    public int computeVerticalScrollOffset() {
+    protected int computeVerticalScrollOffset() {
         return mCurrentScrollOffset;
     }
 
     @Override
-    public int computeVerticalScrollRange() {
-        return mSelectorIndices.length * mSelectorElementHeight;
+    protected int computeVerticalScrollRange() {
+        return (mMaxValue - mMinValue + 1) * mSelectorElementHeight;
+    }
+
+    @Override
+    protected int computeVerticalScrollExtent() {
+        return getHeight();
     }
 
     @Override
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index c72c770..91056f1 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -24,10 +24,10 @@
     boolean getBoolean(in String key, in boolean defaultValue, in int userId);
     long getLong(in String key, in long defaultValue, in int userId);
     String getString(in String key, in String defaultValue, in int userId);
-    void setLockPattern(in byte[] hash, int userId);
-    boolean checkPattern(in byte[] hash, int userId);
-    void setLockPassword(in byte[] hash, int userId);
-    boolean checkPassword(in byte[] hash, int userId);
+    void setLockPattern(in String pattern, int userId);
+    boolean checkPattern(in String pattern, int userId);
+    void setLockPassword(in String password, int userId);
+    boolean checkPassword(in String password, int userId);
     boolean havePattern(int userId);
     boolean havePassword(int userId);
     void removeUser(int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 1f2ab93..8adc7b6 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -32,7 +32,6 @@
 import android.os.UserHandle;
 import android.os.storage.IMountService;
 import android.provider.Settings;
-import android.security.KeyStore;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -292,11 +291,7 @@
     public boolean checkPattern(List<LockPatternView.Cell> pattern) {
         final int userId = getCurrentOrCallingUserId();
         try {
-            final boolean matched = getLockSettings().checkPattern(patternToHash(pattern), userId);
-            if (matched && (userId == UserHandle.USER_OWNER)) {
-                KeyStore.getInstance().password(patternToString(pattern));
-            }
-            return matched;
+            return getLockSettings().checkPattern(patternToString(pattern), userId);
         } catch (RemoteException re) {
             return true;
         }
@@ -311,12 +306,7 @@
     public boolean checkPassword(String password) {
         final int userId = getCurrentOrCallingUserId();
         try {
-            final boolean matched = getLockSettings().checkPassword(passwordToHash(password),
-                    userId);
-            if (matched && (userId == UserHandle.USER_OWNER)) {
-                KeyStore.getInstance().password(password);
-            }
-            return matched;
+            return getLockSettings().checkPassword(password, userId);
         } catch (RemoteException re) {
             return true;
         }
@@ -505,14 +495,10 @@
      * @param isFallback Specifies if this is a fallback to biometric weak
      */
     public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback) {
-        // Compute the hash
-        final byte[] hash = LockPatternUtils.patternToHash(pattern);
         try {
-            getLockSettings().setLockPattern(hash, getCurrentOrCallingUserId());
+            getLockSettings().setLockPattern(patternToString(pattern), getCurrentOrCallingUserId());
             DevicePolicyManager dpm = getDevicePolicyManager();
-            KeyStore keyStore = KeyStore.getInstance();
             if (pattern != null) {
-                keyStore.password(patternToString(pattern));
                 setBoolean(PATTERN_EVER_CHOSEN_KEY, true);
                 if (!isFallback) {
                     deleteGallery();
@@ -528,9 +514,6 @@
                             0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
                 }
             } else {
-                if (keyStore.isEmpty()) {
-                    keyStore.reset();
-                }
                 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
                         0, 0, 0, 0, 0, getCurrentOrCallingUserId());
             }
@@ -637,19 +620,13 @@
      * @param userHandle The userId of the user to change the password for
      */
     public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) {
-        // Compute the hash
-        final byte[] hash = passwordToHash(password);
         try {
-            getLockSettings().setLockPassword(hash, userHandle);
+            getLockSettings().setLockPassword(password, userHandle);
             DevicePolicyManager dpm = getDevicePolicyManager();
-            KeyStore keyStore = KeyStore.getInstance();
             if (password != null) {
                 if (userHandle == UserHandle.USER_OWNER) {
                     // Update the encryption password.
                     updateEncryptionPassword(password);
-
-                    // Update the keystore password
-                    keyStore.password(password);
                 }
 
                 int computedQuality = computePasswordQuality(password);
@@ -709,6 +686,7 @@
                 if (passwordHistoryLength == 0) {
                     passwordHistory = "";
                 } else {
+                    byte[] hash = passwordToHash(password);
                     passwordHistory = new String(hash) + "," + passwordHistory;
                     // Cut it to contain passwordHistoryLength hashes
                     // and passwordHistoryLength -1 commas.
@@ -718,11 +696,6 @@
                 }
                 setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
             } else {
-                // Conditionally reset the keystore if empty. If
-                // non-empty, we are just switching key guard type
-                if (keyStore.isEmpty()) {
-                    keyStore.reset();
-                }
                 dpm.setActivePasswordState(
                         DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0,
                         userHandle);
@@ -803,7 +776,7 @@
      * @param pattern the gesture pattern.
      * @return the hash of the pattern in a byte array.
      */
-    private static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
+    public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
         if (pattern == null) {
             return null;
         }
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 2846e61..0d9a386 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -138,7 +138,8 @@
     DroidSansHebrew-Regular.ttf \
     DroidSansHebrew-Bold.ttf \
     DroidSansArmenian.ttf \
-    DroidSansGeorgian.ttf
+    DroidSansGeorgian.ttf \
+    AndroidEmoji.ttf
 
 endif # !MINIMAL_FONT
 
diff --git a/data/fonts/AndroidEmoji.ttf b/data/fonts/AndroidEmoji.ttf
new file mode 100644
index 0000000..98f72e7
--- /dev/null
+++ b/data/fonts/AndroidEmoji.ttf
Binary files differ
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 69db6aa..ede7ef4 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -186,6 +186,11 @@
     </family>
     <family>
         <fileset>
+            <file>AndroidEmoji.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
             <file>NotoColorEmoji.ttf</file>
         </fileset>
     </family>
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index a677c4f..05cca13e 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -43,6 +43,7 @@
     DroidSansMono.ttf \
     DroidSansArmenian.ttf \
     DroidSansGeorgian.ttf \
+    AndroidEmoji.ttf \
     Clockopia.ttf \
     AndroidClock.ttf \
     AndroidClock_Highlight.ttf \
diff --git a/docs/html/about/index.jd b/docs/html/about/index.jd
index 1573cc3..215fc3c 100644
--- a/docs/html/about/index.jd
+++ b/docs/html/about/index.jd
@@ -53,7 +53,7 @@
 multitude of device form-factors, chipset architectures, and price points. From
 multicore processing and high-performance graphics to state-of-the-art sensors,
 vibrant touchscreens, and emerging mobile technologies such as Near Field
-Communication (NFC), Wi-Fi Direct, and face tracking.</p> -->
+Communication (NFC), Wi-Fi P2P, and face tracking.</p> -->
 
 <h3>Powerful development framework</h3>
 
diff --git a/docs/html/about/versions/android-4.0-highlights.jd b/docs/html/about/versions/android-4.0-highlights.jd
index 9fdb02c..f2b35ac 100644
--- a/docs/html/about/versions/android-4.0-highlights.jd
+++ b/docs/html/about/versions/android-4.0-highlights.jd
@@ -610,14 +610,17 @@
 unlock, or use a backup PIN or pattern. </p>
 
 
-<p style="margin-top:1em;margin-bottom:.75em;"><strong>Wi-Fi Direct and Bluetooth HDP</strong></p>
+<p style="margin-top:1em;margin-bottom:.75em;"><strong>Wi-Fi P2P and Bluetooth HDP</strong></p>
 
-<p>Support for <strong>Wi-Fi Direct</strong> lets users connect directly to
-nearby peer devices over Wi-Fi, for more reliable, higher-speed communication.
-No internet connection or tethering is needed. Through third-party apps, users
-can connect to compatible devices to take advantage of new features such as
-instant sharing of files, photos, or other media; streaming video or audio from
-another device; or connecting to compatible printers or other devices.</p>
+<p>Support for <strong>Wi-Fi peer-to-peer (P2P)</strong> lets users connect directly to nearby peer
+devices over Wi-Fi, for more reliable, higher-speed communication (in compliance with the Wi-Fi
+Alliance's <a href="http://www.wi-fi.org/discover-and-learn/wi-fi-direct"
+ class="external-link">Wi-Fi Direct&trade;</a>
+certification program). No internet connection or tethering is needed. Through third-party apps,
+users can connect to compatible devices to take advantage of new features such as instant sharing
+of files, photos, or other media; streaming video or audio from another device; or connecting to
+compatible printers or other devices.</p>
+
 
 <p>Android 4.0 also introduces built-in support for connecting to <strong>Bluetooth Health Device Profile (HDP)</strong> devices. With support from third-party apps, users can connect to wireless medical devices and sensors in hospitals, fitness centers, homes, and elsewhere.</p>
 
@@ -868,16 +871,19 @@
 
 <h3 id="connectivity-dev">New types of connectivity</h3>
 
-<p style="margin-top:1em;margin-bottom:.75em;"><strong>Wi-Fi Direct</strong></p>
+<p style="margin-top:1em;margin-bottom:.75em;"><strong>Wi-Fi P2P</strong></p>
 
-<p>Developers can use a framework API to discover and connect directly to nearby
-devices over a high-performance, secure Wi-Fi Direct connection. No internet
-connection or hotspot is needed.</p>
+<p>Developers can use a framework API to discover and connect directly to nearby devices over a
+high-performance, secure Wi-Fi peer-to-peer (P2P) connection. No internet connection or hotspot is
+needed. Android's Wi-Fi P2P framework complies with the Wi-Fi Alliance's <a href=
+"http://www.wi-fi.org/discover-and-learn/wi-fi-direct" class="external-link">Wi-Fi Direct&trade;</a>
+certification program.</p>
 
-<p>Wi-Fi Direct opens new opportunities for developers to add innovative
-features to their applications. Applications can use Wi-Fi Direct to share
+
+<p>Wi-Fi peer-to-peer (P2P) opens new opportunities for developers to add innovative
+features to their applications. Applications can use Wi-Fi P2P to share
 files, photos, or other media between devices or between a desktop computer and
-an Android-powered device. Applications could also use Wi-Fi Direct to stream
+an Android-powered device. Applications could also use Wi-Fi P2P to stream
 media content from a peer device such as a digital television or audio player,
 connect a group of users for gaming, print files, and more.</p>
 
diff --git a/docs/html/about/versions/android-4.0.jd b/docs/html/about/versions/android-4.0.jd
index c026534..6c4ccb4 100644
--- a/docs/html/about/versions/android-4.0.jd
+++ b/docs/html/about/versions/android-4.0.jd
@@ -619,12 +619,14 @@
 
 <h3 id="WiFiDirect">Wi-Fi P2P</h3>
 
-<p>Android now supports Wi-Fi peer-to-peer (P2P) connections between Android-powered
-devices and other device types (in compliance with the Wi-Fi
-Alliance's Wi-Fi Direct&trade; certification program) without a hotspot or Internet connection. The Android framework
-provides a set of Wi-Fi P2P APIs that allow you to discover and connect to other devices when each
-device supports Wi-Fi P2P, then communicate over a speedy connection across distances much longer
-than a Bluetooth connection.</p>
+<p>Android now supports Wi-Fi peer-to-peer (P2P) connections between Android-powered devices and
+other device types (in compliance with the Wi-Fi Alliance's <a href=
+"http://www.wi-fi.org/discover-and-learn/wi-fi-direct" class="external-link">Wi-Fi Direct&trade;</a>
+certification program) without a hotspot or Internet connection. The Android framework provides a
+set of Wi-Fi P2P APIs that allow you to discover and connect to other devices when each device
+supports Wi-Fi P2P, then communicate over a speedy connection across distances much longer than a
+Bluetooth connection.</p>
+
 
 <p>A new package, {@link android.net.wifi.p2p}, contains all the APIs for performing peer-to-peer
 connections with Wi-Fi. The primary class you need to work with is {@link
diff --git a/docs/html/about/versions/jelly-bean.jd b/docs/html/about/versions/jelly-bean.jd
index 5deb190..c7d1941 100644
--- a/docs/html/about/versions/jelly-bean.jd
+++ b/docs/html/about/versions/jelly-bean.jd
@@ -860,13 +860,13 @@
 
 <h3 id="42-wireless-display">Wireless display</h3>
 
-<p>Starting in Android 4.2, users on supported devices can connect to an
-external display over Wi-Fi, using <a
-href="http://www.wi-fi.org/wi-fi-certified-miracast%E2%84%A2">Miracast</a>, a
-peer-to-peer wireless display standard created by the <a
-href="http://www.wi-fi.org/">Wi-Fi Alliance</a>. When a wireless display is
-connected, users can stream any type of content to the big screen, including
-photos, games, maps, and more.</p>
+<p>Starting in Android 4.2, users on supported devices can connect to an external display over
+Wi-Fi, using Wi-Fi Display (a peer-to-peer wireless display solution that complies with the
+<a href="http://www.wi-fi.org/wi-fi-certified-miracast%E2%84%A2"
+ class="external-link">Miracast&trade;</a> certification
+program). When a wireless display is connected, users can stream any type of content to the big
+screen, including photos, games, maps, and more.</p>
+
 
 <p>Apps can take advantage of <strong>wireless displays</strong> in the same way as they do other
 external displays and no extra work is needed. The system manages the network
@@ -1455,15 +1455,22 @@
 
 <p>You can take advantage of this API to build new features into your apps. For example, you could let users connect to a webcam, a printer, or an app on another mobile device that supports Wi-Fi peer-to-peer connections.  </p>
 
-<h3>Wi-Fi Direct Service Discovery</h3>
+<h3>Wi-Fi P2P Service Discovery</h3>
 
-<p>Ice Cream Sandwich introduced support for Wi-Fi Direct, a technology that lets apps <strong>discover and pair directly</strong>, over a high-bandwidth peer-to-peer connection. Wi-Fi Direct is an ideal way to share media, photos, files and other types of data and sessions, even where there is no cell network or Wi-Fi available.</p>
+<p><a href="{@docRoot}about/versions/android-4.0-highlights.html">Ice Cream Sandwich</a> introduced
+support for Wi-Fi Peer-to-Peer (P2P), a technology that lets apps <strong>discover and pair
+directly</strong>, over a high-bandwidth peer-to-peer connection (in compliance with the Wi-Fi
+Alliance's <a href="http://www.wi-fi.org/discover-and-learn/wi-fi-direct"
+ class="external-link">Wi-Fi Direct&trade;</a>
+certification program). Wi-Fi P2P is an ideal way to share media, photos, files and other types of
+data and sessions, even where there is no cell network or Wi-Fi available.</p>
 
-<p>Android 4.1 takes Wi-Fi Direct further, adding API support for <strong>pre-associated service discovery</strong>. Pre-associated service discovery lets your apps get more useful information from nearby devices about the services they support, before they attempt to connect.  Apps can initiate discovery for a specific service and filter the list of discovered devices to those that actually support the target service or application.</p>
 
-<p>For example, this means that your app could discover only devices that are “printers” or that have a specific game available, instead of discovering all nearby Wi-Fi Direct devices. On the other hand, your app can advertise the service it provides to other devices, which can discover it and then negotiate a connection. This greatly simplifies discovery and pairing for users and lets apps take advantage of Wi-Fi Direct more effectively.</p>
+<p>Android 4.1 takes Wi-Fi P2P further, adding API support for <strong>pre-associated service discovery</strong>. Pre-associated service discovery lets your apps get more useful information from nearby devices about the services they support, before they attempt to connect.  Apps can initiate discovery for a specific service and filter the list of discovered devices to those that actually support the target service or application.</p>
 
-<p>With Wi-Fi Direct service discovery, you can create apps and <strong>multiplayer games</strong> that can share photos, videos, gameplay, scores, or almost anything else &mdash; all without requiring any Internet or mobile network. Your users can connect using only a direct p2p connection, which avoids using mobile bandwidth.</p>
+<p>For example, this means that your app could discover only devices that are “printers” or that have a specific game available, instead of discovering all nearby Wi-Fi P2P devices. On the other hand, your app can advertise the service it provides to other devices, which can discover it and then negotiate a connection. This greatly simplifies discovery and pairing for users and lets apps take advantage of Wi-Fi P2P more effectively.</p>
+
+<p>With Wi-Fi P2P service discovery, you can create apps and <strong>multiplayer games</strong> that can share photos, videos, gameplay, scores, or almost anything else &mdash; all without requiring any Internet or mobile network. Your users can connect using only a direct p2p connection, which avoids using mobile bandwidth.</p>
 
 <h3>Network Bandwidth Management</h3>
 
diff --git a/docs/html/guide/topics/connectivity/index.jd b/docs/html/guide/topics/connectivity/index.jd
index 322518e..385cf08 100644
--- a/docs/html/guide/topics/connectivity/index.jd
+++ b/docs/html/guide/topics/connectivity/index.jd
@@ -1,6 +1,6 @@
 page.title=Connectivity
 page.landing=true
-page.landing.intro=Android provides rich APIs to let your app connect and interact with other devices over Bluetooth, NFC, Wi-Fi Direct, USB, and SIP, in addition to standard network connections.
+page.landing.intro=Android provides rich APIs to let your app connect and interact with other devices over Bluetooth, NFC, Wi-Fi P2P, USB, and SIP, in addition to standard network connections.
 page.landing.image=images/develop/connectivity.png
 
 @jd:body
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index 14a1682..c62510b 100644
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -10,7 +10,7 @@
 
     <ol>
       <li><a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a></li>
-      <li><a href="#access-rs-apis">Accessing RenderScript Java APIs</a>
+      <li><a href="#access-rs-apis">Accessing RenderScript APIs</a>
         <ol>
           <li><a href="#ide-setup">Setting Up Your Development Environment</a></li>
         </ol>
@@ -150,19 +150,24 @@
 precision (such as SIMD CPU instructions).</p>
 
 
-<h2 id="access-rs-apis">Accessing RenderScript Java APIs</h2>
+<h2 id="access-rs-apis">Accessing RenderScript APIs</h2>
 
-<p>When developing an Android application that uses RenderScript, you can access its Java API in
-  one of two ways. The APIs are available in the {@link android.renderscript} package
-  on devices running Android 3.0 (API level 11) and higher. These are the original APIs for
-  RenderScript. The APIs are also available as a Support Library in the
-  {@link android.support.v8.renderscript} package, which allow you to use them on devices running
-  Android 2.2 (API level 8) and higher.</p>
+<p>When developing an Android application that uses RenderScript, you can access its API in
+  one of two ways:</p>
+
+<ul>
+  <li><strong>{@link android.renderscript}</strong> - The APIs in this class package are
+    available on devices running Android 3.0 (API level 11) and higher. These are the original APIs
+    for RenderScript and are not currently being updated.</li>
+  <li><strong>{@link android.support.v8.renderscript}</strong> - The APIs in this package are
+    available through a <a href="{@docRoot}tools/support-library/features.html#v8">Support
+    Library</a>, which allows you to use them on devices running Android 2.2 (API level 8) and
+    higher.</li>
+</ul>
 
 <p>We strongly recommend using the Support Library APIs for accessing RenderScript because they
   include the latest improvements to the RenderScript compute framework and provide a wider range
-  of device compatibility. Using the RenderScript APIs in the Support Library requires specific
-  setup procedures for your development environment, which is described in the next section.</p>
+  of device compatibility.</p>
 
 
 <h3 id="ide-setup">Using the RenderScript Support Library APIs</h3>
@@ -218,9 +223,9 @@
     back to a compatible version if the device it is running on does not support the target version.
     </li>
   <li>{@code sdk.buildtools} - The version of the Android SDK build tools to use. This value
-    should be set to 18.1.0 or higher. If this option is not specified, the highest installed build
-    tools version is used. You should always set this value to ensure the consistency of builds
-    across development machines with different configurations.</li>
+    should be set to {@code 18.1.0} or higher. If this option is not specified, the highest
+    installed build tools version is used. You should always set this value to ensure the
+    consistency of builds across development machines with different configurations.</li>
 </ul>
 
 
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 0581435..118958d 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -5,43 +5,43 @@
 page.metaDescription=Download the official Android SDK to develop apps for Android-powered devices.
 
 
-sdk.linux32_bundle_download=adt-bundle-linux-x86-20130911.zip
-sdk.linux32_bundle_bytes=474916528
-sdk.linux32_bundle_checksum=7eacc7124299ea99a8fa15c59123540f
+sdk.linux32_bundle_download=adt-bundle-linux-x86-20130917.zip
+sdk.linux32_bundle_bytes=474924071
+sdk.linux32_bundle_checksum=912b2dac6e0a4fa4ae1417271bf42863
 
-sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20130911.zip
-sdk.linux64_bundle_bytes=475207785
-sdk.linux64_bundle_checksum=daa5794a27be7c7fa708c3d28833b0d3
+sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20130917.zip
+sdk.linux64_bundle_bytes=475215747
+sdk.linux64_bundle_checksum=2f7523d4eba9a8302c3c4a3955785e18
 
-sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20130911.zip
-sdk.mac64_bundle_bytes=448575446
-sdk.mac64_bundle_checksum=a1e0cbcc820ae734cfdf439c40811b4c
+sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20130917.zip
+sdk.mac64_bundle_bytes=448581372
+sdk.mac64_bundle_checksum=4e2d599486ecc935d24eeef5eb641364
 
-sdk.win32_bundle_download=adt-bundle-windows-x86-20130911.zip
-sdk.win32_bundle_bytes=481794820
-sdk.win32_bundle_checksum=88a2f4f242aac44f4b1c53e6eccc8710
+sdk.win32_bundle_download=adt-bundle-windows-x86-20130917.zip
+sdk.win32_bundle_bytes=481803289
+sdk.win32_bundle_checksum=5d6c79a47c8b47170cff3d231dcf7ad3
 
-sdk.win64_bundle_download=adt-bundle-windows-x86_64-20130911.zip
-sdk.win64_bundle_bytes=481927327
-sdk.win64_bundle_checksum=e3fa9b7e38af9ed9ac0e99fce3c7026c
+sdk.win64_bundle_download=adt-bundle-windows-x86_64-20130917.zip
+sdk.win64_bundle_bytes=481934982
+sdk.win64_bundle_checksum=918f80aad61ec21509d86a2fbd87fd44
 
 
 
-sdk.linux_download=android-sdk_r22.2-linux.tgz
-sdk.linux_bytes=100909403
-sdk.linux_checksum=2a3776839e823ba9acb7a87a3fe26e02
+sdk.linux_download=android-sdk_r22.2.1-linux.tgz
+sdk.linux_bytes=100918342
+sdk.linux_checksum=05911d3052a1cbf678561104d35a1bc0
 
-sdk.mac_download=android-sdk_r22.2-macosx.zip
-sdk.mac_bytes=74857114
-sdk.mac_checksum=9dfef6404e2f842c433073796aed8b7d
+sdk.mac_download=android-sdk_r22.2.1-macosx.zip
+sdk.mac_bytes=74859877
+sdk.mac_checksum=727a51affa2af733eca1aa307c73c3bd
 
-sdk.win_download=android-sdk_r22.2-windows.zip
-sdk.win_bytes=108790714
-sdk.win_checksum=1ac4c104378cd53049daa6c4458ec544
+sdk.win_download=android-sdk_r22.2.1-windows.zip
+sdk.win_bytes=108676651
+sdk.win_checksum=3b3f63ae00cf946d1174fa08b37d8542
 
-sdk.win_installer=installer_r22.2-windows.exe
-sdk.win_installer_bytes=88788974
-sdk.win_installer_checksum=e5503fa059297d2b18475c086ac6e80c
+sdk.win_installer=installer_r22.2.1-windows.exe
+sdk.win_installer_bytes=88795776
+sdk.win_installer_checksum=07e6e47de6c4549bea6986453119b37c
 
 
 
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index e038d20..66b1c43 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
 page.title=Installing the Eclipse Plugin
-adt.zip.version=22.2.0
-adt.zip.download=ADT-22.2.0.zip
-adt.zip.bytes=14474195
-adt.zip.checksum=52892c9e3b1ad2d1e6edd50e48b2a127
+adt.zip.version=22.2.1
+adt.zip.download=ADT-22.2.1.zip
+adt.zip.bytes=14476845
+adt.zip.checksum=97176754a1e86adf2e5e05f44dc7229e
 
 @jd:body
 
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index 151707a..cfdf8cc 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -57,6 +57,40 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>ADT 22.2.1</a> <em>(September 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Java 1.6 or higher is required.</li>
+      <li>Eclipse Helios (Version 3.6.2) or higher is required.</li>
+      <li>This version of ADT is designed for use with
+        <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r22.2.1</a>.
+        If you haven't already installed SDK Tools r22.2.1 into your SDK, use the
+        Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>General Notes:</dt>
+  <dd>
+    <ul>
+      <li>Fixed problem with templates that causes the new project wizard to hang.
+       (<a href="http://b.android.com/60149">Issue 60149</a>)</li>
+    </ul>
+  </dd>
+
+</dl>
+</div>
+</div>
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>ADT 22.2</a> <em>(September 2013)</em>
   </p>
 
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index e8c4717..25c409e 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -30,6 +30,40 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>SDK Tools, Revision 22.2.1</a> <em>(September 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <dl>
+    <dt>Dependencies:</dt>
+    <dd>
+      <ul>
+        <li>Android SDK Platform-tools revision 16 or later.</li>
+        <li>If you are developing in Eclipse with ADT, note that this version of SDK Tools is
+          designed for use with ADT 22.2.1 and later. If you haven't already, update your
+        <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 22.2.1.</li>
+        <li>If you are developing outside Eclipse, you must have
+          <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+      </ul>
+    </dd>
+
+    <dt>General Notes:</dt>
+    <dd>
+      <ul>
+        <li>Fixed problem with templates that causes the new project wizard to hang.
+         (<a href="http://b.android.com/60149">Issue 60149</a>)</li>
+        <li>Fixed crash when using the lint command line tool because of mis-matched library
+          dependency. (<a href="http://b.android.com/60190">Issue 60190</a>)</li>
+      </ul>
+    </dd>
+    </dl>
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>SDK Tools, Revision 22.2</a> <em>(September 2013)</em>
   </p>
 
diff --git a/docs/html/training/connect-devices-wirelessly/nsd-wifi-direct.jd b/docs/html/training/connect-devices-wirelessly/nsd-wifi-direct.jd
index 8dc5fd9..5c1321e 100644
--- a/docs/html/training/connect-devices-wirelessly/nsd-wifi-direct.jd
+++ b/docs/html/training/connect-devices-wirelessly/nsd-wifi-direct.jd
@@ -1,7 +1,4 @@
 page.title=Using Wi-Fi P2P for Service Discovery
-parent.title=Connecting Devices Wirelessly
-parent.link=index.html
-
 trainingnavtop=true
 
 @jd:body
diff --git a/docs/html/training/connect-devices-wirelessly/nsd.jd b/docs/html/training/connect-devices-wirelessly/nsd.jd
index 30f5c49..e07e2af 100644
--- a/docs/html/training/connect-devices-wirelessly/nsd.jd
+++ b/docs/html/training/connect-devices-wirelessly/nsd.jd
@@ -1,10 +1,6 @@
 page.title=Using Network Service Discovery
-parent.title=Connecting Devices Wirelessly
-parent.link=index.html
 
 trainingnavtop=true
-next.title=Connecting with Wi-Fi Direct
-next.link=wifi-direct.html
 
 @jd:body
 
diff --git a/docs/html/training/connect-devices-wirelessly/wifi-direct.jd b/docs/html/training/connect-devices-wirelessly/wifi-direct.jd
index 98435c6..d67ed23 100644
--- a/docs/html/training/connect-devices-wirelessly/wifi-direct.jd
+++ b/docs/html/training/connect-devices-wirelessly/wifi-direct.jd
@@ -23,8 +23,10 @@
 </div>
 
 <p>The Wi-Fi peer-to-peer (P2P) APIs allow applications to connect to nearby devices without
-needing to connect to a network or hotspot (Android's Wi-Fi P2P framework complies with the Wi-Fi
-Alliance's Wi-Fi Direct&trade; certification program).  Wi-Fi P2P allows your application to quickly
+needing to connect to a network or hotspot (Android's Wi-Fi P2P framework complies with the
+<a href="http://www.wi-fi.org/discover-and-learn/wi-fi-direct"
+ class="external-link">Wi-Fi Direct&trade;</a> certification program).
+ Wi-Fi P2P allows your application to quickly
 find and interact with nearby devices, at a range beyond the capabilities of Bluetooth.
 </p>
 <p>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 0c4f9df..8c2752e 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -418,7 +418,7 @@
           </a>
           </li>
           <li><a href="<?cs var:toroot ?>training/connect-devices-wirelessly/nsd-wifi-direct.html">
-            Using Wi-Fi Direct for Service Discovery
+            Using Wi-Fi P2P for Service Discovery
           </a>
           </li>
         </ul>
diff --git a/packages/DocumentsUI/res/animator/dir_down.xml b/packages/DocumentsUI/res/animator/dir_down.xml
new file mode 100644
index 0000000..7f547f1
--- /dev/null
+++ b/packages/DocumentsUI/res/animator/dir_down.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:valueFrom="1"
+    android:valueTo="0"
+    android:propertyName="position"
+    android:valueType="floatType"
+    android:duration="@android:integer/config_mediumAnimTime"
+    android:interpolator="@android:interpolator/decelerate_quad" />
diff --git a/packages/DocumentsUI/res/animator/dir_frozen.xml b/packages/DocumentsUI/res/animator/dir_frozen.xml
new file mode 100644
index 0000000..b541d13
--- /dev/null
+++ b/packages/DocumentsUI/res/animator/dir_frozen.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:valueFrom="0"
+    android:valueTo="0"
+    android:propertyName="position"
+    android:valueType="floatType"
+    android:duration="@android:integer/config_mediumAnimTime" />
diff --git a/packages/DocumentsUI/res/animator/dir_up.xml b/packages/DocumentsUI/res/animator/dir_up.xml
new file mode 100644
index 0000000..fda0faf
--- /dev/null
+++ b/packages/DocumentsUI/res/animator/dir_up.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:valueFrom="0"
+    android:valueTo="1"
+    android:propertyName="position"
+    android:valueType="floatType"
+    android:duration="@android:integer/config_mediumAnimTime"
+    android:interpolator="@android:interpolator/accelerate_quad" />
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_doc_album.png b/packages/DocumentsUI/res/drawable-hdpi/ic_doc_album.png
new file mode 100644
index 0000000..a1e2b7f
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_doc_album.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_doc_generic.png b/packages/DocumentsUI/res/drawable-hdpi/ic_doc_generic.png
new file mode 100644
index 0000000..68d973f
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_doc_generic.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_doc_pdf.png b/packages/DocumentsUI/res/drawable-hdpi/ic_doc_pdf.png
index c86b92d..7e2bef1 100644
--- a/packages/DocumentsUI/res/drawable-hdpi/ic_doc_pdf.png
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_doc_pdf.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_grid_folder.png b/packages/DocumentsUI/res/drawable-hdpi/ic_grid_folder.png
new file mode 100644
index 0000000..7c9aee3
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_grid_folder.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_menu_new_folder.png b/packages/DocumentsUI/res/drawable-hdpi/ic_menu_new_folder.png
index 06adf31..490d7ca 100644
--- a/packages/DocumentsUI/res/drawable-hdpi/ic_menu_new_folder.png
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_menu_new_folder.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_menu_overflow.png b/packages/DocumentsUI/res/drawable-hdpi/ic_menu_overflow.png
new file mode 100644
index 0000000..d49b58f
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_menu_overflow.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_popout.png b/packages/DocumentsUI/res/drawable-hdpi/ic_popout.png
new file mode 100644
index 0000000..f89f813
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_popout.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_doc_album.png b/packages/DocumentsUI/res/drawable-mdpi/ic_doc_album.png
new file mode 100644
index 0000000..adf23f4
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_doc_album.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_doc_generic.png b/packages/DocumentsUI/res/drawable-mdpi/ic_doc_generic.png
new file mode 100644
index 0000000..f73ab71
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_doc_generic.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_doc_pdf.png b/packages/DocumentsUI/res/drawable-mdpi/ic_doc_pdf.png
index ff51096..4fca711 100644
--- a/packages/DocumentsUI/res/drawable-mdpi/ic_doc_pdf.png
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_doc_pdf.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_grid_folder.png b/packages/DocumentsUI/res/drawable-mdpi/ic_grid_folder.png
new file mode 100644
index 0000000..7cf9178
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_grid_folder.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_menu_overflow.png b/packages/DocumentsUI/res/drawable-mdpi/ic_menu_overflow.png
new file mode 100644
index 0000000..795a28d
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_menu_overflow.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_popout.png b/packages/DocumentsUI/res/drawable-mdpi/ic_popout.png
new file mode 100644
index 0000000..98a853f
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_popout.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_dialog_alert.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_dialog_alert.png
index d824bb0..7d1468a 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_dialog_alert.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_dialog_alert.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow.9.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow.9.png
new file mode 100644
index 0000000..0240874
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_doc_album.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_doc_album.png
new file mode 100644
index 0000000..29e009e
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_doc_album.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_doc_generic.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_doc_generic.png
new file mode 100644
index 0000000..82cf876
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_doc_generic.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_doc_pdf.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_doc_pdf.png
index 518e591..3e94790 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_doc_pdf.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_doc_pdf.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_grid_folder.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_grid_folder.png
new file mode 100644
index 0000000..3344980
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_grid_folder.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_copy.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_copy.png
index 946e450..614b1e3 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_copy.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_copy.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_new_folder.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_new_folder.png
index 4af42d4..f94d3f6 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_new_folder.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_new_folder.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_overflow.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_overflow.png
new file mode 100644
index 0000000..0603bbf
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_overflow.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_share.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_share.png
index bdd8e20..1cf6dca 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_share.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_share.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_undo.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_undo.png
index 34a0e33..0cadd92 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_undo.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_undo.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_view_grid.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_view_grid.png
index c955fc3..8ec013c 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_view_grid.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_view_grid.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_view_list.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_view_list.png
index a23c73a..45dd72f 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_view_list.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_view_list.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_popout.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_popout.png
new file mode 100644
index 0000000..3a33bce
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_popout.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_root_download.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_root_download.png
index f66739d..6f64d8c 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_root_download.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_root_download.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_root_recent.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_root_recent.png
index 7e24377..000a521 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_root_recent.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_root_recent.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_root_sdcard.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_root_sdcard.png
index 0ce9f9f..223cff1 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_root_sdcard.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_root_sdcard.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_root_usb.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_root_usb.png
index dde7586..d77023b 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_root_usb.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_root_usb.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_dialog_alert.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_dialog_alert.png
index 887b1b5..865f3a5 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_dialog_alert.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_dialog_alert.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_doc_album.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_doc_album.png
new file mode 100644
index 0000000..7515993
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_doc_album.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_doc_generic.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_doc_generic.png
new file mode 100644
index 0000000..c459556
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_doc_generic.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_doc_pdf.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_doc_pdf.png
index dd94dda..cd46f79 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_doc_pdf.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_doc_pdf.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_grid_folder.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_grid_folder.png
new file mode 100644
index 0000000..86a74cd
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_grid_folder.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_copy.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_copy.png
index 2a0cfc2..1f72cce 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_copy.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_copy.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_new_folder.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_new_folder.png
index fb40707..038a597 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_new_folder.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_new_folder.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_overflow.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_overflow.png
new file mode 100644
index 0000000..58f1381
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_overflow.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_share.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_share.png
index 0a3ac2e..9084717 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_share.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_share.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_undo.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_undo.png
index fd0a194..eec1b95 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_undo.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_undo.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_view_grid.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_view_grid.png
index 11ec8da..175a76c 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_view_grid.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_view_grid.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_view_list.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_view_list.png
index ed3b0c5..07c7c02 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_view_list.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_view_list.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_popout.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_popout.png
new file mode 100644
index 0000000..5f5a86f
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_popout.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_download.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_download.png
index f22a94a..d68f9c5 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_download.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_download.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_recent.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_recent.png
index 09cac0e..d95ebb5 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_recent.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_recent.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_sdcard.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_sdcard.png
index 5349252..cc27107 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_sdcard.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_sdcard.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_usb.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_usb.png
index 6deafc7..1562609 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_usb.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_root_usb.png
Binary files differ
diff --git a/packages/DocumentsUI/res/layout/activity.xml b/packages/DocumentsUI/res/layout/activity.xml
index ff28e41..9937c39 100644
--- a/packages/DocumentsUI/res/layout/activity.xml
+++ b/packages/DocumentsUI/res/layout/activity.xml
@@ -24,7 +24,7 @@
         android:layout_height="match_parent"
         android:orientation="vertical">
 
-        <FrameLayout
+        <com.android.documentsui.DirectoryContainerView
             android:id="@+id/container_directory"
             android:layout_width="match_parent"
             android:layout_height="0dip"
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index b4138a5..07bf127 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -14,9 +14,10 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.documentsui.DirectoryView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:background="@drawable/ic_dir_shadow">
 
     <TextView
         android:id="@android:id/empty"
@@ -40,4 +41,4 @@
         android:listSelector="@android:color/transparent"
         android:visibility="gone" />
 
-</FrameLayout>
+</com.android.documentsui.DirectoryView>
diff --git a/packages/DocumentsUI/res/values-sw720dp/styles.xml b/packages/DocumentsUI/res/values-sw720dp/styles.xml
index 4ff1c60..a581e08 100644
--- a/packages/DocumentsUI/res/values-sw720dp/styles.xml
+++ b/packages/DocumentsUI/res/values-sw720dp/styles.xml
@@ -16,6 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <style name="Theme" parent="@android:style/Theme.Holo.Light">
+        <item name="android:actionOverflowButtonStyle">@style/DarkerOverflow</item>
         <item name="android:windowBackground">@*android:drawable/dialog_full_holo_light</item>
         <item name="android:colorBackgroundCacheHint">@null</item>
         <item name="android:windowIsTranslucent">true</item>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 945e7ae..0c8f712 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -29,5 +29,12 @@
 
     <!-- Normally just a redirection, but this is used to make ourselves a
          dialog on large tablets -->
-    <style name="Theme" parent="@android:style/Theme.Holo.Light" />
+    <style name="Theme" parent="@android:style/Theme.Holo.Light">
+        <item name="android:actionOverflowButtonStyle">@style/DarkerOverflow</item>
+    </style>
+    
+    <style name="DarkerOverflow" parent="@android:style/Widget.Holo.Light.ActionButton.Overflow">
+        <item name="android:src">@drawable/ic_menu_overflow</item>
+    </style>
+
 </resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryContainerView.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryContainerView.java
new file mode 100644
index 0000000..77595b6
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryContainerView.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 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.documentsui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+
+public class DirectoryContainerView extends FrameLayout {
+    private boolean mDisappearingFirst = false;
+
+    public DirectoryContainerView(Context context) {
+        super(context);
+        setClipChildren(false);
+    }
+
+    public DirectoryContainerView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setClipChildren(false);
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        final ArrayList<View> disappearing = mDisappearingChildren;
+        if (mDisappearingFirst && disappearing != null) {
+            for (int i = 0; i < disappearing.size(); i++) {
+                super.drawChild(canvas, disappearing.get(i), getDrawingTime());
+            }
+        }
+        super.dispatchDraw(canvas);
+    }
+
+    @Override
+    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+        if (mDisappearingFirst && mDisappearingChildren != null
+                && mDisappearingChildren.contains(child)) {
+            return false;
+        }
+        return super.drawChild(canvas, child, drawingTime);
+    }
+
+    public void setDrawDisappearingFirst(boolean disappearingFirst) {
+        mDisappearingFirst = disappearingFirst;
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 198927c..4c2c99c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -43,12 +43,14 @@
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.os.Parcelable;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.text.format.DateUtils;
 import android.text.format.Formatter;
 import android.text.format.Time;
 import android.util.Log;
+import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.view.ActionMode;
 import android.view.LayoutInflater;
@@ -96,7 +98,13 @@
     public static final int TYPE_SEARCH = 2;
     public static final int TYPE_RECENT_OPEN = 3;
 
+    public static final int ANIM_NONE = 1;
+    public static final int ANIM_SIDE = 2;
+    public static final int ANIM_DOWN = 3;
+    public static final int ANIM_UP = 4;
+
     private int mType = TYPE_NORMAL;
+    private String mStateKey;
 
     private int mLastMode = MODE_UNKNOWN;
     private int mLastSortOrder = SORT_ORDER_UNKNOWN;
@@ -113,39 +121,61 @@
     private static final String EXTRA_ROOT = "root";
     private static final String EXTRA_DOC = "doc";
     private static final String EXTRA_QUERY = "query";
+    private static final String EXTRA_IGNORE_STATE = "ignoreState";
 
     private static AtomicInteger sLoaderId = new AtomicInteger(4000);
 
     private final int mLoaderId = sLoaderId.incrementAndGet();
 
-    public static void showNormal(FragmentManager fm, RootInfo root, DocumentInfo doc) {
-        show(fm, TYPE_NORMAL, root, doc, null);
+    public static void showNormal(FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
+        show(fm, TYPE_NORMAL, root, doc, null, anim);
     }
 
-    public static void showSearch(FragmentManager fm, RootInfo root, String query) {
-        show(fm, TYPE_SEARCH, root, null, query);
+    public static void showSearch(FragmentManager fm, RootInfo root, String query, int anim) {
+        show(fm, TYPE_SEARCH, root, null, query, anim);
     }
 
-    public static void showRecentsOpen(FragmentManager fm) {
-        show(fm, TYPE_RECENT_OPEN, null, null, null);
+    public static void showRecentsOpen(FragmentManager fm, int anim) {
+        show(fm, TYPE_RECENT_OPEN, null, null, null, anim);
     }
 
-    private static void show(
-            FragmentManager fm, int type, RootInfo root, DocumentInfo doc, String query) {
+    private static void show(FragmentManager fm, int type, RootInfo root, DocumentInfo doc,
+            String query, int anim) {
         final Bundle args = new Bundle();
         args.putInt(EXTRA_TYPE, type);
         args.putParcelable(EXTRA_ROOT, root);
         args.putParcelable(EXTRA_DOC, doc);
         args.putString(EXTRA_QUERY, query);
 
+        final FragmentTransaction ft = fm.beginTransaction();
+        switch (anim) {
+            case ANIM_SIDE:
+                args.putBoolean(EXTRA_IGNORE_STATE, true);
+                break;
+            case ANIM_DOWN:
+                args.putBoolean(EXTRA_IGNORE_STATE, true);
+                ft.setCustomAnimations(R.animator.dir_down, R.animator.dir_frozen);
+                break;
+            case ANIM_UP:
+                ft.setCustomAnimations(R.animator.dir_frozen, R.animator.dir_up);
+                break;
+        }
+
         final DirectoryFragment fragment = new DirectoryFragment();
         fragment.setArguments(args);
 
-        final FragmentTransaction ft = fm.beginTransaction();
         ft.replace(R.id.container_directory, fragment);
         ft.commitAllowingStateLoss();
     }
 
+    private static String buildStateKey(RootInfo root, DocumentInfo doc) {
+        final StringBuilder builder = new StringBuilder();
+        builder.append(root != null ? root.authority : "null").append(';');
+        builder.append(root != null ? root.rootId : "null").append(';');
+        builder.append(doc != null ? doc.documentId : "null");
+        return builder.toString();
+    }
+
     public static DirectoryFragment get(FragmentManager fm) {
         // TODO: deal with multiple directories shown at once
         return (DirectoryFragment) fm.findFragmentById(R.id.container_directory);
@@ -184,6 +214,7 @@
 
         mAdapter = new DocumentsAdapter();
         mType = getArguments().getInt(EXTRA_TYPE);
+        mStateKey = buildStateKey(root, doc);
 
         if (mType == TYPE_RECENT_OPEN) {
             // Hide titles when showing recents for picking images/videos
@@ -241,11 +272,16 @@
 
                 updateDisplayState();
 
-                if (mLastSortOrder != state.derivedSortOrder) {
-                    mLastSortOrder = state.derivedSortOrder;
+                // Restore any previous instance state
+                final SparseArray<Parcelable> container = state.dirState.remove(mStateKey);
+                if (container != null && !getArguments().getBoolean(EXTRA_IGNORE_STATE, false)) {
+                    getView().restoreHierarchyState(container);
+                } else if (mLastSortOrder != state.derivedSortOrder) {
                     mListView.smoothScrollToPosition(0);
                     mGridView.smoothScrollToPosition(0);
                 }
+
+                mLastSortOrder = state.derivedSortOrder;
             }
 
             @Override
@@ -261,6 +297,17 @@
     }
 
     @Override
+    public void onStop() {
+        super.onStop();
+
+        // Remember last scroll location
+        final SparseArray<Parcelable> container = new SparseArray<Parcelable>();
+        getView().saveHierarchyState(container);
+        final State state = getDisplayState(this);
+        state.dirState.put(mStateKey, container);
+    }
+
+    @Override
     public void onResume() {
         super.onResume();
         updateDisplayState();
@@ -734,7 +781,8 @@
                     iconMime.setImageDrawable(
                             IconUtils.loadPackageIcon(context, docAuthority, docIcon));
                 } else {
-                    iconMime.setImageDrawable(IconUtils.loadMimeIcon(context, docMimeType));
+                    iconMime.setImageDrawable(IconUtils.loadMimeIcon(
+                            context, docMimeType, docAuthority, docId, state.derivedMode));
                 }
             }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
new file mode 100644
index 0000000..34cb14fd
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 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.documentsui;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+public class DirectoryView extends FrameLayout {
+    private float mPosition = 0f;
+
+    private int mWidth;
+
+    public DirectoryView(Context context) {
+        super(context);
+    }
+
+    public DirectoryView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void setBackground(Drawable background) {
+        final Rect rect = new Rect();
+        background.getPadding(rect);
+        final InsetDrawable inset = new InsetDrawable(background, -rect.left, 0, 0, 0);
+        super.setBackground(inset);
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mWidth = w;
+        setPosition(mPosition);
+    }
+
+    public float getPosition() {
+        return mPosition;
+    }
+
+    public void setPosition(float position) {
+        mPosition = position;
+        setX((mWidth > 0) ? (mPosition * mWidth) : 0);
+        setAlpha(1f - position);
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index f6cb481..3b71f60 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -16,6 +16,10 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
+import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
+import static com.android.documentsui.DirectoryFragment.ANIM_SIDE;
+import static com.android.documentsui.DirectoryFragment.ANIM_UP;
 import static com.android.documentsui.DocumentsActivity.State.ACTION_CREATE;
 import static com.android.documentsui.DocumentsActivity.State.ACTION_GET_CONTENT;
 import static com.android.documentsui.DocumentsActivity.State.ACTION_MANAGE;
@@ -44,6 +48,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
 import android.support.v4.app.ActionBarDrawerToggle;
@@ -51,6 +56,7 @@
 import android.support.v4.widget.DrawerLayout;
 import android.support.v4.widget.DrawerLayout.DrawerListener;
 import android.util.Log;
+import android.util.SparseArray;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -73,12 +79,14 @@
 import com.android.documentsui.model.DocumentStack;
 import com.android.documentsui.model.DurableUtils;
 import com.android.documentsui.model.RootInfo;
+import com.google.common.collect.Maps;
 
 import libcore.io.IoUtils;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 
 public class DocumentsActivity extends Activity {
@@ -94,6 +102,8 @@
     private ActionBarDrawerToggle mDrawerToggle;
     private View mRootsContainer;
 
+    private DirectoryContainerView mDirectoryContainer;
+
     private boolean mIgnoreNextNavigation;
     private boolean mIgnoreNextClose;
     private boolean mIgnoreNextCollapse;
@@ -165,6 +175,8 @@
             mRootsContainer = findViewById(R.id.container_roots);
         }
 
+        mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
+
         if (icicle != null) {
             mState = icicle.getParcelable(EXTRA_STATE);
         } else {
@@ -195,7 +207,7 @@
             RootsFragment.show(getFragmentManager(), null);
         }
 
-        onCurrentDirectoryChanged();
+        onCurrentDirectoryChanged(ANIM_NONE);
     }
 
     private void buildDefaultState() {
@@ -397,7 +409,7 @@
             public boolean onQueryTextSubmit(String query) {
                 mState.currentSearch = query;
                 mSearchView.clearFocus();
-                onCurrentDirectoryChanged();
+                onCurrentDirectoryChanged(ANIM_NONE);
                 return true;
             }
 
@@ -421,7 +433,7 @@
                 }
 
                 mState.currentSearch = null;
-                onCurrentDirectoryChanged();
+                onCurrentDirectoryChanged(ANIM_NONE);
                 return true;
             }
         });
@@ -435,7 +447,7 @@
                 }
 
                 mState.currentSearch = null;
-                onCurrentDirectoryChanged();
+                onCurrentDirectoryChanged(ANIM_NONE);
                 return false;
             }
         });
@@ -595,7 +607,7 @@
         final int size = mState.stack.size();
         if (size > 1) {
             mState.stack.pop();
-            onCurrentDirectoryChanged();
+            onCurrentDirectoryChanged(ANIM_UP);
         } else if (size == 1 && !isRootsDrawerOpen()) {
             // TODO: open root drawer once we can capture back key
             super.onBackPressed();
@@ -690,7 +702,7 @@
                 mState.stackTouched = true;
                 mState.stack.pop();
             }
-            onCurrentDirectoryChanged();
+            onCurrentDirectoryChanged(ANIM_UP);
             return true;
         }
     };
@@ -711,17 +723,19 @@
         return mState;
     }
 
-    private void onCurrentDirectoryChanged() {
+    private void onCurrentDirectoryChanged(int anim) {
         final FragmentManager fm = getFragmentManager();
         final RootInfo root = getCurrentRoot();
         final DocumentInfo cwd = getCurrentDirectory();
 
+        mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
+
         if (cwd == null) {
             // No directory means recents
             if (mState.action == ACTION_CREATE) {
                 RecentsCreateFragment.show(fm);
             } else {
-                DirectoryFragment.showRecentsOpen(fm);
+                DirectoryFragment.showRecentsOpen(fm, anim);
 
                 // Start recents in relevant mode
                 final boolean acceptImages = MimePredicate.mimeMatches(
@@ -732,10 +746,10 @@
         } else {
             if (mState.currentSearch != null) {
                 // Ongoing search
-                DirectoryFragment.showSearch(fm, root, mState.currentSearch);
+                DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
             } else {
                 // Normal boring directory
-                DirectoryFragment.showNormal(fm, root, cwd);
+                DirectoryFragment.showNormal(fm, root, cwd, anim);
             }
         }
 
@@ -760,7 +774,7 @@
     public void onStackPicked(DocumentStack stack) {
         mState.stack = stack;
         mState.stackTouched = true;
-        onCurrentDirectoryChanged();
+        onCurrentDirectoryChanged(ANIM_SIDE);
     }
 
     public void onRootPicked(RootInfo root, boolean closeDrawer) {
@@ -772,11 +786,14 @@
         if (!mRoots.isRecentsRoot(root)) {
             try {
                 final Uri uri = DocumentsContract.buildDocumentUri(root.authority, root.documentId);
-                onDocumentPicked(DocumentInfo.fromUri(getContentResolver(), uri));
+                final DocumentInfo doc = DocumentInfo.fromUri(getContentResolver(), uri);
+                mState.stack.push(doc);
+                mState.stackTouched = true;
+                onCurrentDirectoryChanged(ANIM_SIDE);
             } catch (FileNotFoundException e) {
             }
         } else {
-            onCurrentDirectoryChanged();
+            onCurrentDirectoryChanged(ANIM_SIDE);
         }
 
         if (closeDrawer) {
@@ -798,7 +815,7 @@
         if (doc.isDirectory()) {
             mState.stack.push(doc);
             mState.stackTouched = true;
-            onCurrentDirectoryChanged();
+            onCurrentDirectoryChanged(ANIM_DOWN);
         } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
             // Explicit file picked, return
             onFinished(doc.derivedUri);
@@ -924,6 +941,9 @@
         /** Currently active search, overriding any stack. */
         public String currentSearch;
 
+        /** Instance state for every shown directory */
+        public HashMap<String, SparseArray<Parcelable>> dirState = Maps.newHashMap();
+
         public static final int ACTION_OPEN = 1;
         public static final int ACTION_CREATE = 2;
         public static final int ACTION_GET_CONTENT = 3;
@@ -956,6 +976,7 @@
             out.writeInt(stackTouched ? 1 : 0);
             DurableUtils.writeToParcel(out, stack);
             out.writeString(currentSearch);
+            out.writeMap(dirState);
         }
 
         public static final Creator<State> CREATOR = new Creator<State>() {
@@ -973,6 +994,7 @@
                 state.stackTouched = in.readInt() != 0;
                 DurableUtils.readFromParcel(in, state.stack);
                 state.currentSearch = in.readString();
+                in.readMap(state.dirState, null);
                 return state;
             }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
index 5caf9ba..1f7386c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
@@ -22,6 +22,7 @@
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.provider.DocumentsContract.Document;
+import android.util.Log;
 
 import com.google.android.collect.Maps;
 
@@ -206,6 +207,27 @@
         return null;
     }
 
+    public static Drawable loadMimeIcon(
+            Context context, String mimeType, String authority, String docId, int mode) {
+        final Resources res = context.getResources();
+
+        if (Document.MIME_TYPE_DIR.equals(mimeType)) {
+            // TODO: eventually move these hacky assets into that package
+            if ("com.android.providers.media.documents".equals(authority)
+                    && docId.startsWith("album")) {
+                return res.getDrawable(R.drawable.ic_doc_album);
+            }
+
+            if (mode == DocumentsActivity.State.MODE_GRID) {
+                return res.getDrawable(R.drawable.ic_grid_folder);
+            } else {
+                return res.getDrawable(R.drawable.ic_root_folder);
+            }
+        }
+
+        return loadMimeIcon(context, mimeType);
+    }
+
     public static Drawable loadMimeIcon(Context context, String mimeType) {
         final Resources res = context.getResources();
 
@@ -236,8 +258,7 @@
         } else if ("video".equals(typeOnly)) {
             return res.getDrawable(R.drawable.ic_doc_video);
         } else {
-            // TODO: generic icon?
-            return null;
+            return res.getDrawable(R.drawable.ic_doc_generic);
         }
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
index 2d96876..9df55a0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
@@ -80,10 +80,10 @@
     }
 
     public static boolean mimeMatches(String filter, String test) {
-        if (filter == null || "*/*".equals(filter)) {
-            return true;
-        } else if (test == null) {
+        if (test == null) {
             return false;
+        } else if (filter == null || "*/*".equals(filter)) {
+            return true;
         } else if (filter.equals(test)) {
             return true;
         } else if (filter.endsWith("/*")) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 8ab4645..34e87cc 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -139,7 +139,7 @@
     private static final int MIN_COPIES = 1;
     private static final String MIN_COPIES_STRING = String.valueOf(MIN_COPIES);
 
-    private static final Pattern PATTERN_DIGITS = Pattern.compile("\\d");
+    private static final Pattern PATTERN_DIGITS = Pattern.compile("[\\d]+");
 
     private static final Pattern PATTERN_ESCAPE_SPECIAL_CHARS = Pattern.compile(
             "(?=[]\\[+&|!(){}^\"~*?:\\\\])");
@@ -1484,7 +1484,8 @@
                         fromIndex = toIndex = Integer.parseInt(range) - 1;
                     }
 
-                    PageRange pageRange = new PageRange(fromIndex, toIndex);
+                    PageRange pageRange = new PageRange(Math.min(fromIndex, toIndex),
+                            Math.max(fromIndex, toIndex));
                     pageRanges.add(pageRange);
                 }
 
@@ -2166,6 +2167,11 @@
                 return false;
             }
 
+            if (ourPageRanges.length == 1
+                    && PageRange.ALL_PAGES.equals(ourPageRanges[0])) {
+                return true;
+            }
+
             otherPageRanges = normalize(otherPageRanges);
 
             int otherPageIdx = 0;
@@ -2197,28 +2203,28 @@
             if (pageRanges == null) {
                 return null;
             }
-            final int oldPageCount = pageRanges.length;
-            if (oldPageCount <= 1) {
+            final int oldRangeCount = pageRanges.length;
+            if (oldRangeCount <= 1) {
                 return pageRanges;
             }
             Arrays.sort(pageRanges, sComparator);
-            int newRangeCount = 0;
-            for (int i = 0; i < oldPageCount - 1; i++) {
+            int newRangeCount = 1;
+            for (int i = 0; i < oldRangeCount - 1; i++) {
                 newRangeCount++;
                 PageRange currentRange = pageRanges[i];
                 PageRange nextRange = pageRanges[i + 1];
-                if (currentRange.getEnd() >= nextRange.getStart()) {
+                if (currentRange.getEnd() + 1 >= nextRange.getStart()) {
                     newRangeCount--;
                     pageRanges[i] = null;
                     pageRanges[i + 1] = new PageRange(currentRange.getStart(),
-                            nextRange.getEnd());
+                            Math.max(currentRange.getEnd(), nextRange.getEnd()));
                 }
             }
-            if (newRangeCount == oldPageCount) {
+            if (newRangeCount == oldRangeCount) {
                 return pageRanges;
             }
-            return Arrays.copyOfRange(pageRanges, oldPageCount - newRangeCount,
-                    oldPageCount - 1);
+            return Arrays.copyOfRange(pageRanges, oldRangeCount - newRangeCount,
+                    oldRangeCount);
         }
 
         public static void offsetStart(PageRange[] pageRanges, int offset) {
diff --git a/services/java/com/android/server/LockSettingsService.java b/services/java/com/android/server/LockSettingsService.java
index c5555c8..cd746cf 100644
--- a/services/java/com/android/server/LockSettingsService.java
+++ b/services/java/com/android/server/LockSettingsService.java
@@ -40,6 +40,7 @@
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.provider.Settings.SettingNotFoundException;
+import android.security.KeyStore;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
@@ -80,11 +81,14 @@
     private static final String LOCK_PASSWORD_FILE = "password.key";
 
     private final Context mContext;
+    private LockPatternUtils mLockPatternUtils;
 
     public LockSettingsService(Context context) {
         mContext = context;
         // Open the database
         mOpenHelper = new DatabaseHelper(mContext);
+
+        mLockPatternUtils = new LockPatternUtils(context);
     }
 
     public void systemReady() {
@@ -255,15 +259,42 @@
         return new File(getLockPatternFilename(userId)).length() > 0;
     }
 
+    private void maybeUpdateKeystore(String password, int userId) {
+        if (userId == UserHandle.USER_OWNER) {
+            final KeyStore keyStore = KeyStore.getInstance();
+            // Conditionally reset the keystore if empty. If non-empty, we are just
+            // switching key guard type
+            if (TextUtils.isEmpty(password) && keyStore.isEmpty()) {
+                keyStore.reset();
+            } else {
+                // Update the keystore password
+                keyStore.password(password);
+            }
+        }
+    }
+
     @Override
-    public void setLockPattern(byte[] hash, int userId) throws RemoteException {
+    public void setLockPattern(String pattern, int userId) throws RemoteException {
         checkWritePermission(userId);
 
+        maybeUpdateKeystore(pattern, userId);
+
+        final byte[] hash = LockPatternUtils.patternToHash(
+                LockPatternUtils.stringToPattern(pattern));
         writeFile(getLockPatternFilename(userId), hash);
     }
 
     @Override
-    public boolean checkPattern(byte[] hash, int userId) throws RemoteException {
+    public void setLockPassword(String password, int userId) throws RemoteException {
+        checkWritePermission(userId);
+
+        maybeUpdateKeystore(password, userId);
+
+        writeFile(getLockPasswordFilename(userId), mLockPatternUtils.passwordToHash(password));
+    }
+
+    @Override
+    public boolean checkPattern(String pattern, int userId) throws RemoteException {
         checkPasswordReadPermission(userId);
         try {
             // Read all the bytes from the file
@@ -275,25 +306,23 @@
                 return true;
             }
             // Compare the hash from the file with the entered pattern's hash
-            return Arrays.equals(stored, hash);
+            final byte[] hash = LockPatternUtils.patternToHash(
+                    LockPatternUtils.stringToPattern(pattern));
+            final boolean matched = Arrays.equals(stored, hash);
+            if (matched && !TextUtils.isEmpty(pattern)) {
+                maybeUpdateKeystore(pattern, userId);
+            }
+            return matched;
         } catch (FileNotFoundException fnfe) {
             Slog.e(TAG, "Cannot read file " + fnfe);
-            return true;
         } catch (IOException ioe) {
             Slog.e(TAG, "Cannot read file " + ioe);
-            return true;
         }
+        return true;
     }
 
     @Override
-    public void setLockPassword(byte[] hash, int userId) throws RemoteException {
-        checkWritePermission(userId);
-
-        writeFile(getLockPasswordFilename(userId), hash);
-    }
-
-    @Override
-    public boolean checkPassword(byte[] hash, int userId) throws RemoteException {
+    public boolean checkPassword(String password, int userId) throws RemoteException {
         checkPasswordReadPermission(userId);
 
         try {
@@ -306,14 +335,18 @@
                 return true;
             }
             // Compare the hash from the file with the entered password's hash
-            return Arrays.equals(stored, hash);
+            final byte[] hash = mLockPatternUtils.passwordToHash(password);
+            final boolean matched = Arrays.equals(stored, hash);
+            if (matched && !TextUtils.isEmpty(password)) {
+                maybeUpdateKeystore(password, userId);
+            }
+            return matched;
         } catch (FileNotFoundException fnfe) {
             Slog.e(TAG, "Cannot read file " + fnfe);
-            return true;
         } catch (IOException ioe) {
             Slog.e(TAG, "Cannot read file " + ioe);
-            return true;
         }
+        return true;
     }
 
     @Override
@@ -445,13 +478,12 @@
         private void maybeEnableWidgetSettingForUsers(SQLiteDatabase db) {
             final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
             final ContentResolver cr = mContext.getContentResolver();
-            final LockPatternUtils utils = new LockPatternUtils(mContext);
             final List<UserInfo> users = um.getUsers();
             for (int i = 0; i < users.size(); i++) {
                 final int userId = users.get(i).id;
-                final boolean enabled = utils.hasWidgetsEnabledInKeyguard(userId);
+                final boolean enabled = mLockPatternUtils.hasWidgetsEnabledInKeyguard(userId);
                 Log.v(TAG, "Widget upgrade uid=" + userId + ", enabled="
-                        + enabled + ", w[]=" + utils.getAppWidgets());
+                        + enabled + ", w[]=" + mLockPatternUtils.getAppWidgets());
                 loadSetting(db, LockPatternUtils.LOCKSCREEN_WIDGETS_ENABLED, userId, enabled);
             }
         }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 676b330..f08b5b9 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -21,12 +21,12 @@
 import static com.android.internal.util.XmlUtils.writeIntAttribute;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
+
 import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
 
 import android.app.AppOpsManager;
 import android.appwidget.AppWidgetManager;
 import android.util.ArrayMap;
-
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IAppOpsService;
@@ -52,7 +52,6 @@
 import com.android.server.wm.AppTransition;
 import com.android.server.wm.StackBox;
 import com.android.server.wm.WindowManagerService;
-
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
@@ -155,7 +154,6 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.format.Time;
-import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.EventLog;
 import android.util.Log;
@@ -519,7 +517,7 @@
      * This is the process holding what we currently consider to be
      * the "home" activity.
      */
-    ArraySet<ProcessRecord> mHomeProcess = new ArraySet<ProcessRecord>();
+    ProcessRecord mHomeProcess;
 
     /**
      * This is the process holding the activity the user last visited that
@@ -9122,8 +9120,8 @@
         // with a home activity running in the process to prevent a repeatedly crashing app
         // from blocking the user to manually clear the list.
         final ArrayList<ActivityRecord> activities = app.activities;
-        if (mHomeProcess.contains(app) && activities.size() > 0
-                    && (app.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+        if (app == mHomeProcess && activities.size() > 0
+                    && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                 final ActivityRecord r = activities.get(activityNdx);
                 if (r.isHomeActivity()) {
@@ -10400,20 +10398,13 @@
                 pw.print("  mStartedUserArray: "); pw.println(Arrays.toString(mStartedUserArray));
             }
         }
-        if (!mHomeProcess.isEmpty()) {
-            final int size = mHomeProcess.size();
-            ProcessRecord[] processes = new ProcessRecord[size];
-            mHomeProcess.toArray(processes);
-            for (int processNdx = 0; processNdx < size; ++processNdx) {
-                final ProcessRecord app = processes[processNdx];
-                if (dumpPackage == null || app.pkgList.containsKey(dumpPackage)) {
-                    if (needSep) {
-                        pw.println();
-                        needSep = false;
-                    }
-                    pw.println("  mHomeProcess[" + processNdx + "]: " + app);
-                }
+        if (mHomeProcess != null && (dumpPackage == null
+                || mHomeProcess.pkgList.containsKey(dumpPackage))) {
+            if (needSep) {
+                pw.println();
+                needSep = false;
             }
+            pw.println("  mHomeProcess: " + mHomeProcess);
         }
         if (mPreviousProcess != null && (dumpPackage == null
                 || mPreviousProcess.pkgList.containsKey(dumpPackage))) {
@@ -11943,8 +11934,6 @@
         }
         mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
 
-        mHomeProcess.remove(app);
-
         // If the caller is restarting this app, then leave it in its
         // current lists and let the caller take care of it.
         if (restarting) {
@@ -11974,8 +11963,8 @@
                 "Clean-up removing on hold: " + app);
         mProcessesOnHold.remove(app);
 
-        if (mHomeProcess.contains(app)) {
-            mHomeProcess.remove(app);
+        if (app == mHomeProcess) {
+            mHomeProcess = null;
         }
         if (app == mPreviousProcess) {
             mPreviousProcess = null;
@@ -13904,7 +13893,7 @@
             }
         }
 
-        if (mHomeProcess.contains(app)) {
+        if (app == mHomeProcess) {
             if (adj > ProcessList.HOME_APP_ADJ) {
                 // This process is hosting what we currently consider to be the
                 // home app, so we don't want to let it go into the background.
@@ -13971,7 +13960,7 @@
                 if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
                     procState = ActivityManager.PROCESS_STATE_SERVICE;
                 }
-                if (app.hasShownUi && !mHomeProcess.contains(app)) {
+                if (app.hasShownUi && app != mHomeProcess) {
                     // If this process has shown some UI, let it immediately
                     // go to the LRU list because it may be pretty heavy with
                     // UI stuff.  We'll tag it with a label just to help
@@ -14034,7 +14023,7 @@
                         if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                             // Not doing bind OOM management, so treat
                             // this guy more like a started service.
-                            if (app.hasShownUi && !mHomeProcess.contains(app)) {
+                            if (app.hasShownUi && app != mHomeProcess) {
                                 // If this process has shown some UI, let it immediately
                                 // go to the LRU list because it may be pretty heavy with
                                 // UI stuff.  We'll tag it with a label just to help
@@ -14089,7 +14078,7 @@
                             // about letting this process get into the LRU
                             // list to be killed and restarted if needed for
                             // memory.
-                            if (app.hasShownUi && !mHomeProcess.contains(app)
+                            if (app.hasShownUi && app != mHomeProcess
                                     && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                 adjType = "cch-bound-ui-services";
                             } else {
@@ -14203,7 +14192,7 @@
                     clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                 }
                 if (adj > clientAdj) {
-                    if (app.hasShownUi && !mHomeProcess.contains(app)
+                    if (app.hasShownUi && app != mHomeProcess
                             && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                         app.adjType = "cch-ui-provider";
                     } else {
@@ -15065,7 +15054,7 @@
                             // to be good enough at this point that destroying
                             // activities causes more harm than good.
                             if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
-                                    && !mHomeProcess.contains(app) && app != mPreviousProcess) {
+                                    && app != mHomeProcess && app != mPreviousProcess) {
                                 // Need to do this on its own message because the stack may not
                                 // be in a consistent state at this point.
                                 // For these apps we will also finish their activities
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index c31c213..1482440 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2254,7 +2254,7 @@
                 if (r.state == ActivityState.RESUMED
                         || r.state == ActivityState.PAUSING
                         || r.state == ActivityState.PAUSED) {
-                    if (!r.isHomeActivity() || !mService.mHomeProcess.contains(r.app)) {
+                    if (!r.isHomeActivity() || mService.mHomeProcess != r.app) {
                         Slog.w(TAG, "  Force finishing activity "
                                 + r.intent.getComponent().flattenToShortString());
                         finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 8ad29f3..219cb85 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -906,7 +906,8 @@
                         r.task.taskId, r.shortComponentName);
             }
             if (r.isHomeActivity() && r.isNotResolverActivity()) {
-                mService.mHomeProcess.add(app);
+                // Home process is the root process of the task.
+                mService.mHomeProcess = r.task.mActivities.get(0).app;
             }
             mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
             r.sleeping = false;
@@ -1949,7 +1950,7 @@
         // makes sense to.
         if (r.app != null && fgApp != null && r.app != fgApp
                 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
-                && !mService.mHomeProcess.contains(r.app)) {
+                && r.app != mService.mHomeProcess) {
             mService.mPreviousProcess = r.app;
             mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
         }
diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/java/com/android/server/connectivity/PacManager.java
index 772921a..53e1dc2 100644
--- a/services/java/com/android/server/connectivity/PacManager.java
+++ b/services/java/com/android/server/connectivity/PacManager.java
@@ -252,7 +252,7 @@
         Intent intent = new Intent();
         intent.setClassName(PAC_PACKAGE, PAC_SERVICE);
         // Already bound no need to bind again.
-        if (mProxyConnection != null) {
+        if ((mProxyConnection != null) && (mConnection != null)) {
             if (mLastPort != -1) {
                 sendPacBroadcast(new ProxyProperties(mPacUrl, mLastPort));
             } else {
@@ -332,10 +332,15 @@
     }
 
     private void unbind() {
-        mContext.unbindService(mConnection);
-        mContext.unbindService(mProxyConnection);
-        mConnection = null;
-        mProxyConnection = null;
+        if (mConnection != null) {
+            mContext.unbindService(mConnection);
+            mConnection = null;
+        }
+        if (mProxyConnection != null) {
+            mContext.unbindService(mProxyConnection);
+            mProxyConnection = null;
+        }
+        mProxyService = null;
     }
 
     private void sendPacBroadcast(ProxyProperties proxy) {