Merge "Add support for emulating external storage on devices with no SD card"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ec0d83c..98b0a28 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -72,6 +72,13 @@
          when there's no network connection. If the scan doesn't timeout, use zero -->
     <integer name="config_radioScanningTimeout">0</integer>
 
+    <!-- Set to true if the location returned Environment.getExternalStorageDirectory()
+         is actually a subdirectory of the internal storage.
+         If this is set then Environment.getExternalStorageState() will always return
+         MEDIA_MOUNTED and Intent.ACTION_MEDIA_MOUNTED will be broadcast at boot time
+         for backward compatibility with apps that require external storage. -->
+    <bool name="config_emulateExternalStorage">false</bool>
+
     <!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION.
          Please don't copy them, copy anything else. -->
 
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index d7b92ec..ef5e9cc 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -127,6 +127,8 @@
     private boolean                               mBooted = false;
     private boolean                               mReady = false;
     private boolean                               mSendUmsConnectedOnBoot = false;
+    // true if we should fake MEDIA_MOUNTED state for external storage
+    private boolean                               mEmulateExternalStorage = false;
 
     /**
      * Private hash of currently mounted secure containers.
@@ -319,7 +321,9 @@
                             String path = Environment.getExternalStorageDirectory().getPath();
                             String state = getVolumeState(path);
 
-                            if (state.equals(Environment.MEDIA_UNMOUNTED)) {
+                            if (mEmulateExternalStorage) {
+                                notifyVolumeStateChange(null, path, VolumeState.NoMedia, VolumeState.Mounted);
+                            } else if (state.equals(Environment.MEDIA_UNMOUNTED)) {
                                 int rc = doMountVolume(path);
                                 if (rc != StorageResultCode.OperationSucceeded) {
                                     Slog.e(TAG, String.format("Boot-time mount failed (%d)", rc));
@@ -390,11 +394,13 @@
             Slog.w(TAG, String.format("Duplicate state transition (%s -> %s)", mLegacyState, state));
             return;
         }
-        // Update state on PackageManager
-        if (Environment.MEDIA_UNMOUNTED.equals(state)) {
-            mPms.updateExternalMediaStatus(false, false);
-        } else if (Environment.MEDIA_MOUNTED.equals(state)) {
-            mPms.updateExternalMediaStatus(true, false);
+        // Update state on PackageManager, but only of real events
+        if (!mEmulateExternalStorage) {
+            if (Environment.MEDIA_UNMOUNTED.equals(state)) {
+                mPms.updateExternalMediaStatus(false, false);
+            } else if (Environment.MEDIA_MOUNTED.equals(state)) {
+                mPms.updateExternalMediaStatus(true, false);
+            }
         }
         String oldState = mLegacyState;
         mLegacyState = state;
@@ -894,6 +900,13 @@
     public MountService(Context context) {
         mContext = context;
 
+        mEmulateExternalStorage = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_emulateExternalStorage);
+        if (mEmulateExternalStorage) {
+            Slog.d(TAG, "using emulated external storage");
+            mLegacyState = Environment.MEDIA_MOUNTED;
+        }
+
         // XXX: This will go away soon in favor of IMountServiceObserver
         mPms = (PackageManagerService) ServiceManager.getService("package");