Merge "Do not show roaming icon for Videotron operator when access Canada network" into klp-dev
diff --git a/api/current.txt b/api/current.txt
index 078ed53..8e69592 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3084,18 +3084,18 @@
     method public void cancel(android.app.PendingIntent);
     method public void set(int, long, android.app.PendingIntent);
     method public void setExact(int, long, android.app.PendingIntent);
-    method public deprecated void setInexactRepeating(int, long, long, android.app.PendingIntent);
+    method public void setInexactRepeating(int, long, long, android.app.PendingIntent);
     method public void setRepeating(int, long, long, android.app.PendingIntent);
     method public void setTime(long);
     method public void setTimeZone(java.lang.String);
     method public void setWindow(int, long, long, android.app.PendingIntent);
     field public static final int ELAPSED_REALTIME = 3; // 0x3
     field public static final int ELAPSED_REALTIME_WAKEUP = 2; // 0x2
-    field public static final deprecated long INTERVAL_DAY = 86400000L; // 0x5265c00L
-    field public static final deprecated long INTERVAL_FIFTEEN_MINUTES = 900000L; // 0xdbba0L
-    field public static final deprecated long INTERVAL_HALF_DAY = 43200000L; // 0x2932e00L
-    field public static final deprecated long INTERVAL_HALF_HOUR = 1800000L; // 0x1b7740L
-    field public static final deprecated long INTERVAL_HOUR = 3600000L; // 0x36ee80L
+    field public static final long INTERVAL_DAY = 86400000L; // 0x5265c00L
+    field public static final long INTERVAL_FIFTEEN_MINUTES = 900000L; // 0xdbba0L
+    field public static final long INTERVAL_HALF_DAY = 43200000L; // 0x2932e00L
+    field public static final long INTERVAL_HALF_HOUR = 1800000L; // 0x1b7740L
+    field public static final long INTERVAL_HOUR = 3600000L; // 0x36ee80L
     field public static final int RTC = 1; // 0x1
     field public static final int RTC_WAKEUP = 0; // 0x0
   }
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 27b5a5a9..0cf7ad0 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -48,6 +48,15 @@
  * etc) it is easier and much more efficient to use
  * {@link android.os.Handler}.</b>
  *
+ * <p class="caution"><strong>Note:</strong> Beginning with API 19
+ * ({@link android.os.Build.VERSION_CODES#KITKAT}) alarm delivery is inexact:
+ * the OS will shift alarms in order to minimize wakeups and battery use.  There are
+ * new APIs to support applications which need strict delivery guarantees; see
+ * {@link #setWindow(int, long, long, PendingIntent)} and
+ * {@link #setExact(int, long, PendingIntent)}.  Applications whose {@code targetSdkVersion}
+ * is earlier than API 19 will continue to see the previous behavior in which all
+ * alarms are delivered exactly when requested.
+ *
  * <p>You do not
  * instantiate this class directly; instead, retrieve it through
  * {@link android.content.Context#getSystemService
@@ -132,6 +141,7 @@
      * broadcast.  Recurring alarms that have gone undelivered because the
      * phone was asleep may have a count greater than one when delivered.  
      *
+     * <div class="note">
      * <p>
      * <b>Note:</b> Beginning in API 19, the trigger time passed to this method
      * is treated as inexact: the alarm will not be delivered before this time, but
@@ -144,16 +154,17 @@
      * <p>
      * With the new batching policy, delivery ordering guarantees are not as
      * strong as they were previously.  If the application sets multiple alarms,
-     * it is possible that these alarms' <i>actual</i> delivery ordering may not match
-     * the order of their <i>requested</i> delivery times.  If your application has
+     * it is possible that these alarms' <em>actual</em> delivery ordering may not match
+     * the order of their <em>requested</em> delivery times.  If your application has
      * strong ordering requirements there are other APIs that you can use to get
      * the necessary behavior; see {@link #setWindow(int, long, long, PendingIntent)}
      * and {@link #setExact(int, long, PendingIntent)}.
      *
      * <p>
-     * <b>Note:</b> Applications whose targetSdkVersion is before API 19 will
+     * Applications whose {@code targetSdkVersion} is before API 19 will
      * continue to get the previous alarm behavior: all of their scheduled alarms
      * will be treated as exact.
+     * </div>
      *
      * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
      *        {@link #RTC}, or {@link #RTC_WAKEUP}.
@@ -206,11 +217,11 @@
      * between alarms, then the approach to take is to use one-time alarms, 
      * scheduling the next one yourself when handling each alarm delivery.
      *
-     * <p>
+     * <p class="note">
      * <b>Note:</b> as of API 19, all repeating alarms are inexact.  If your
      * application needs precise delivery times then it must use one-time
      * exact alarms, rescheduling each time as described above. Legacy applications
-     * whose targetSdkVersion is earlier than API 19 will continue to have all
+     * whose {@code targetSdkVersion} is earlier than API 19 will continue to have all
      * of their alarms, including repeating alarms, treated as exact.
      *
      * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
@@ -250,18 +261,19 @@
      * modest timeliness requirements for its alarms.
      *
      * <p>
-     * This method can also be used to achieve strict ordering guarantees by ensuring
-     * that the windows requested for each alarm do not intersect.
+     * This method can also be used to achieve strict ordering guarantees among
+     * multiple alarms by ensuring that the windows requested for each alarm do
+     * not intersect.
      *
      * <p>
      * When precise delivery is not required, applications should use the standard
      * {@link #set(int, long, PendingIntent)} method.  This will give the OS the most
-     * ability to minimize wakeups and battery use.  For alarms that must be delivered
+     * flexibility to minimize wakeups and battery use.  For alarms that must be delivered
      * at precisely-specified times with no acceptable variation, applications can use
      * {@link #setExact(int, long, PendingIntent)}.
      *
      * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
-     *        {@link #RTC}, or {@link #RTC_WAKEUP
+     *        {@link #RTC}, or {@link #RTC_WAKEUP}.
      * @param windowStartMillis The earliest time, in milliseconds, that the alarm should
      *        be delivered, expressed in the appropriate clock's units (depending on the alarm
      *        type).
@@ -355,54 +367,62 @@
     }
 
     /**
-     * @deprecated setInexactRepeating() is deprecated; as of API 19 all
-     * repeating alarms are inexact.
+     * Available inexact recurrence interval recognized by
+     * {@link #setInexactRepeating(int, long, long, PendingIntent)}
+     * when running on Android prior to API 19.
      */
-    @Deprecated
     public static final long INTERVAL_FIFTEEN_MINUTES = 15 * 60 * 1000;
 
     /**
-     * @deprecated setInexactRepeating() is deprecated; as of API 19 all
-     * repeating alarms are inexact.
+     * Available inexact recurrence interval recognized by
+     * {@link #setInexactRepeating(int, long, long, PendingIntent)}
+     * when running on Android prior to API 19.
      */
-    @Deprecated
     public static final long INTERVAL_HALF_HOUR = 2*INTERVAL_FIFTEEN_MINUTES;
 
     /**
-     * @deprecated setInexactRepeating() is deprecated; as of API 19 all
-     * repeating alarms are inexact.
+     * Available inexact recurrence interval recognized by
+     * {@link #setInexactRepeating(int, long, long, PendingIntent)}
+     * when running on Android prior to API 19.
      */
-    @Deprecated
     public static final long INTERVAL_HOUR = 2*INTERVAL_HALF_HOUR;
 
     /**
-     * @deprecated setInexactRepeating() is deprecated; as of API 19 all
-     * repeating alarms are inexact.
+     * Available inexact recurrence interval recognized by
+     * {@link #setInexactRepeating(int, long, long, PendingIntent)}
+     * when running on Android prior to API 19.
      */
-    @Deprecated
     public static final long INTERVAL_HALF_DAY = 12*INTERVAL_HOUR;
 
     /**
-     * @deprecated setInexactRepeating() is deprecated; as of API 19 all
-     * repeating alarms are inexact.
+     * Available inexact recurrence interval recognized by
+     * {@link #setInexactRepeating(int, long, long, PendingIntent)}
+     * when running on Android prior to API 19.
      */
-    @Deprecated
     public static final long INTERVAL_DAY = 2*INTERVAL_HALF_DAY;
 
     /**
      * Schedule a repeating alarm that has inexact trigger time requirements;
      * for example, an alarm that repeats every hour, but not necessarily at
      * the top of every hour.  These alarms are more power-efficient than
-     * the strict recurrences supplied by {@link #setRepeating}, since the
-     * system can adjust alarms' phase to cause them to fire simultaneously,
+     * the strict recurrences traditionally supplied by {@link #setRepeating}, since the
+     * system can adjust alarms' delivery times to cause them to fire simultaneously,
      * avoiding waking the device from sleep more than necessary.
-     * 
+     *
      * <p>Your alarm's first trigger will not be before the requested time,
      * but it might not occur for almost a full interval after that time.  In
      * addition, while the overall period of the repeating alarm will be as
      * requested, the time between any two successive firings of the alarm
      * may vary.  If your application demands very low jitter, use
-     * {@link #setRepeating} instead.
+     * one-shot alarms with an appropriate window instead; see {@link
+     * #setWindow(int, long, long, PendingIntent)} and
+     * {@link #setExact(int, long, PendingIntent)}.
+     *
+     * <p class="note">
+     * As of API 19, all repeating alarms are inexact.  Because this method has
+     * been available since API 3, your application can safely call it and be
+     * assured that it will get similar behavior on both current and older versions
+     * of Android.
      *
      * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
      *        {@link #RTC}, or {@link #RTC_WAKEUP}.
@@ -412,17 +432,17 @@
      * delay of almost an entire alarm interval before the first invocation of
      * the alarm.
      * @param intervalMillis interval in milliseconds between subsequent repeats
-     * of the alarm.  If this is one of INTERVAL_FIFTEEN_MINUTES,
+     * of the alarm.  Prior to API 19, if this is one of INTERVAL_FIFTEEN_MINUTES,
      * INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_HALF_DAY, or INTERVAL_DAY
      * then the alarm will be phase-aligned with other alarms to reduce the
      * number of wakeups.  Otherwise, the alarm will be set as though the
-     * application had called {@link #setRepeating}.
+     * application had called {@link #setRepeating}.  As of API 19, all repeating
+     * alarms will be inexact and subject to batching with other alarms regardless
+     * of their stated repeat interval.
      * @param operation Action to perform when the alarm goes off;
      * typically comes from {@link PendingIntent#getBroadcast
      * IntentSender.getBroadcast()}.
      *
-     * @deprecated As of API 19, all repeating alarms are inexact.
-     *
      * @see android.os.Handler
      * @see #set
      * @see #cancel
@@ -439,7 +459,6 @@
      * @see #INTERVAL_HALF_DAY
      * @see #INTERVAL_DAY
      */
-    @Deprecated
     public void setInexactRepeating(int type, long triggerAtMillis,
             long intervalMillis, PendingIntent operation) {
         setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, operation, null);
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 7f8dca2..09f5fe3 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -81,6 +81,9 @@
     /** {@hide} */
     public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
 
+    /** {@hide} */
+    public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
+
     /**
      * Included in {@link AssetFileDescriptor#getExtras()} when returned
      * thumbnail should be rotated.
diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd
index 3399ee8..f2fd79b 100644
--- a/docs/html/sdk/installing/studio.jd
+++ b/docs/html/sdk/installing/studio.jd
@@ -253,36 +253,36 @@
     <td>Windows</td>
     <td>
   <a onclick="return onDownload(this)" id="win-studio"
-      href="http://dl.google.com/android/studio/android-studio-bundle-130.737825-windows.exe">
-      android-studio-bundle-130.737825-windows.exe
+      href="http://dl.google.com/android/studio/android-studio-bundle-132.883541-windows.exe">
+      android-studio-bundle-132.883541-windows.exe
       </a>
     </td>
-    <td>396091268 bytes</td>
-    <td>6da1bc8effa048c8ff669e4c484eb11f</td>
+    <td>448245492 bytes</td>
+    <td>ca5f5c4d21b4350ddf3bda7021a6ee5e</td>
   </tr>
 
   <tr>
     <td><nobr>Mac OS X</nobr></td>
     <td>
   <a onclick="return onDownload(this)" id="mac-studio"
-    href="http://dl.google.com/android/studio/android-studio-bundle-130.737825-mac.dmg">
-    android-studio-bundle-130.737825-mac.dmg
+    href="http://dl.google.com/android/studio/android-studio-bundle-132.883541-mac.dmg">
+    android-studio-bundle-132.883541-mac.dmg
     </a>
     </td>
-    <td>383326582 bytes</td>
-    <td>2959bc5039238d286670cc6225342b89</td>
+    <td>427317993 bytes</td>
+    <td>67831af6e7896a0a146d43423fabb542</td>
   </tr>
 
   <tr>
     <td>Linux</td>
     <td>
   <a onclick="return onDownload(this)" id="linux-studio"
-    href="http://dl.google.com/android/studio/android-studio-bundle-130.737825-linux.tgz">
-    android-studio-bundle-130.737825-linux.tgz
+    href="http://dl.google.com/android/studio/android-studio-bundle-132.883541-linux.tgz">
+    android-studio-bundle-132.883541-linux.tgz
     </a>
     </td>
-    <td>409935592 bytes</td>
-    <td>dcd13922f7cf577e3c852b224205d843</td>
+    <td>451652493 bytes</td>
+    <td>7a6f9b12b2cd5321ab0818b51306e01c</td>
   </tr>
   </table>
 
@@ -290,9 +290,13 @@
 
 
 
-<h2 id="Updating">Updating to 0.2.x</h2>
+<h2 id="Updating">Updating from older versions</h2>
 
-<p>To update from Android Studio 0.1.x to 0.2.x,
+<p>If you already have Android Studio installed, in most cases, you can upgrade to the latest
+version by installing a patch. From within Android Studio, select
+<strong>Help &gt; Check for updates</strong> to see whether an update is available.</p>
+
+<p>If an update is not available,
 follow the <a href="#Installing">installation instructions</a> below and replace your existing
 installation.</p>
 
@@ -304,13 +308,10 @@
 before installing the update. Then move them back once the update is complete.
 If you fail to copy these packages, then you can instead download them again through
 the Android SDK Manager.</p>
-<p><strong>Windows users:</strong> Do not install Android Studio 0.2.x in the same
-location as 0.1.x. Doing so may cause errors such as ClassCastException or other unexpected
-behaviors. It's best if you remove your previous version of Android Studio 0.1.x.</p>
 </div>
 
 
-<p>Also note that due to the update to Gradle 0.5, you will encounter errors when opening
+<p>Also note that due to the update to Android Gradle Plugin 0.6, you will encounter errors when opening
 existing projects. See the <a href="#Troubleshooting">Troubleshooting</a> notes below for
 information about how to resolve them.</p>
 
@@ -419,16 +420,22 @@
 
 <h2 id="Revisions">Revisions</h2>
 
-<p class="note"><strong>Note:</strong> <strong>There is not a patch update available from
-0.1.9 to 0.2</strong>. To update from Android Studio 0.1.x to 0.2.x, you must
-install a new Android Studio bundle from this page.  The reason for that is that we have made
-changes to the bundled SDK such that it includes a pre-configured local Maven repository
-which can serve up the v4 support library and which is required for creating new projects.</p>
-
-
 <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=""/>Android Studio v0.3.1</a> <em>(Oct 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+  <ul>
+    <li>See <a href="http://tools.android.com/recent">tools.android.com</a> for a full list of changes.</li>
+  </ul>
+  </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=""/>Android Studio v0.2.x</a> <em>(July 2013)</em>
   </p>
 
@@ -610,7 +617,7 @@
   if (os) {
     /* set up primary ACE download button */
     $('#download-ide-button').show();
-    $('#download-ide-button').append("Download Android Studio <span class='small'>v0.2.x</span>"
+    $('#download-ide-button').append("Download Android Studio <span class='small'>v0.3.1</span>"
         + "<br/> <span class='small'>for " + os + "</span>");
     $('#download-ide-button').click(function() {return onDownload(this,true);}).attr('href', bundlename);
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index fa8bc9d..775720e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -84,7 +84,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Display the documents inside a single directory.
@@ -127,9 +126,7 @@
     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();
+    private final int mLoaderId = 42;
 
     public static void showNormal(FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
         show(fm, TYPE_NORMAL, root, doc, null, anim);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index a9278d7..4212e96 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -255,7 +255,9 @@
         }
 
         mState.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
-        mState.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(this);
+        mState.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
+        mState.showAdvanced = mState.forceAdvanced
+                | SettingsActivity.getDisplayAdvancedDevices(this);
     }
 
     private class RestoreRootTask extends AsyncTask<Void, Void, RootInfo> {
@@ -1136,6 +1138,7 @@
         public boolean allowMultiple = false;
         public boolean showSize = false;
         public boolean localOnly = false;
+        public boolean forceAdvanced = false;
         public boolean showAdvanced = false;
         public boolean stackTouched = false;
         public boolean restored = false;
@@ -1176,6 +1179,7 @@
             out.writeInt(allowMultiple ? 1 : 0);
             out.writeInt(showSize ? 1 : 0);
             out.writeInt(localOnly ? 1 : 0);
+            out.writeInt(forceAdvanced ? 1 : 0);
             out.writeInt(showAdvanced ? 1 : 0);
             out.writeInt(stackTouched ? 1 : 0);
             out.writeInt(restored ? 1 : 0);
@@ -1195,6 +1199,7 @@
                 state.allowMultiple = in.readInt() != 0;
                 state.showSize = in.readInt() != 0;
                 state.localOnly = in.readInt() != 0;
+                state.forceAdvanced = in.readInt() != 0;
                 state.showAdvanced = in.readInt() != 0;
                 state.stackTouched = in.readInt() != 0;
                 state.restored = in.readInt() != 0;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 58c5daf..931dac9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -136,7 +136,8 @@
 
         final Context context = getActivity();
         final State state = ((DocumentsActivity) context).getDisplayState();
-        state.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(context);
+        state.showAdvanced = state.forceAdvanced
+                | SettingsActivity.getDisplayAdvancedDevices(context);
 
         if (state.action == ACTION_GET_CONTENT) {
             mList.setOnItemLongClickListener(mItemLongClickListener);
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index d42354f..559e052 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -16,14 +16,17 @@
 
 package com.android.externalstorage;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.database.MatrixCursor.RowBuilder;
 import android.graphics.Point;
+import android.net.Uri;
 import android.os.CancellationSignal;
 import android.os.Environment;
+import android.os.FileObserver;
 import android.os.ParcelFileDescriptor;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
@@ -49,6 +52,8 @@
 public class ExternalStorageProvider extends DocumentsProvider {
     private static final String TAG = "ExternalStorage";
 
+    private static final boolean LOG_INOTIFY = false;
+
     public static final String AUTHORITY = "com.android.externalstorage.documents";
 
     // docId format: root:path/to/file
@@ -83,6 +88,9 @@
     @GuardedBy("mRootsLock")
     private HashMap<String, File> mIdToPath;
 
+    @GuardedBy("mObservers")
+    private Map<File, DirectoryObserver> mObservers = Maps.newHashMap();
+
     @Override
     public boolean onCreate() {
         mStorageManager = (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
@@ -327,8 +335,9 @@
     public Cursor queryChildDocuments(
             String parentDocumentId, String[] projection, String sortOrder)
             throws FileNotFoundException {
-        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
         final File parent = getFileForDocId(parentDocumentId);
+        final MatrixCursor result = new DirectoryCursor(
+                resolveDocumentProjection(projection), parentDocumentId, parent);
         for (File file : parent.listFiles()) {
             includeFile(result, null, file);
         }
@@ -394,7 +403,7 @@
     private static String getTypeForName(String name) {
         final int lastDot = name.lastIndexOf('.');
         if (lastDot >= 0) {
-            final String extension = name.substring(lastDot + 1);
+            final String extension = name.substring(lastDot + 1).toLowerCase();
             final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
             if (mime != null) {
                 return mime;
@@ -411,7 +420,7 @@
     private static String removeExtension(String mimeType, String name) {
         final int lastDot = name.lastIndexOf('.');
         if (lastDot >= 0) {
-            final String extension = name.substring(lastDot + 1);
+            final String extension = name.substring(lastDot + 1).toLowerCase();
             final String nameMime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
             if (mimeType.equals(nameMime)) {
                 return name.substring(0, lastDot);
@@ -431,4 +440,86 @@
         }
         return name;
     }
+
+    private void startObserving(File file, Uri notifyUri) {
+        synchronized (mObservers) {
+            DirectoryObserver observer = mObservers.get(file);
+            if (observer == null) {
+                observer = new DirectoryObserver(
+                        file, getContext().getContentResolver(), notifyUri);
+                observer.startWatching();
+                mObservers.put(file, observer);
+            }
+            observer.mRefCount++;
+
+            if (LOG_INOTIFY) Log.d(TAG, "after start: " + observer);
+        }
+    }
+
+    private void stopObserving(File file) {
+        synchronized (mObservers) {
+            DirectoryObserver observer = mObservers.get(file);
+            if (observer == null) return;
+
+            observer.mRefCount--;
+            if (observer.mRefCount == 0) {
+                mObservers.remove(file);
+                observer.stopWatching();
+            }
+
+            if (LOG_INOTIFY) Log.d(TAG, "after stop: " + observer);
+        }
+    }
+
+    private static class DirectoryObserver extends FileObserver {
+        private static final int NOTIFY_EVENTS = ATTRIB | CLOSE_WRITE | MOVED_FROM | MOVED_TO
+                | CREATE | DELETE | DELETE_SELF | MOVE_SELF;
+
+        private final File mFile;
+        private final ContentResolver mResolver;
+        private final Uri mNotifyUri;
+
+        private int mRefCount = 0;
+
+        public DirectoryObserver(File file, ContentResolver resolver, Uri notifyUri) {
+            super(file.getAbsolutePath(), NOTIFY_EVENTS);
+            mFile = file;
+            mResolver = resolver;
+            mNotifyUri = notifyUri;
+        }
+
+        @Override
+        public void onEvent(int event, String path) {
+            if ((event & NOTIFY_EVENTS) != 0) {
+                if (LOG_INOTIFY) Log.d(TAG, "onEvent() " + event + " at " + path);
+                mResolver.notifyChange(mNotifyUri, null, false);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "DirectoryObserver{file=" + mFile.getAbsolutePath() + ", ref=" + mRefCount + "}";
+        }
+    }
+
+    private class DirectoryCursor extends MatrixCursor {
+        private final File mFile;
+
+        public DirectoryCursor(String[] columnNames, String docId, File file) {
+            super(columnNames);
+
+            final Uri notifyUri = DocumentsContract.buildChildDocumentsUri(
+                    AUTHORITY, docId);
+            setNotificationUri(getContext().getContentResolver(), notifyUri);
+
+            mFile = file;
+            startObserving(mFile, notifyUri);
+        }
+
+        @Override
+        public void close() {
+            super.close();
+            stopObserving(mFile);
+        }
+    }
 }
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index b510643..7650a65 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1471,13 +1471,13 @@
                             // We really do want to push this one into the
                             // user's face, right now.
                             movedHome = true;
+                            targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
                             if ((launchFlags &
                                     (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
                                     == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
                                 // Caller wants to appear on home activity.
                                 intentActivity.task.mOnTopOfHome = true;
                             }
-                            targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
                             options = null;
                         }
                     }