Merge "Avoid overriding DATE_TAKEN by unreliable file time. MediaProvider will calculate it if needed."
diff --git a/Android.mk b/Android.mk
index 35ee3fd..95f38c5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -120,6 +120,7 @@
 	core/java/android/os/IMessenger.aidl \
 	core/java/android/os/storage/IMountService.aidl \
 	core/java/android/os/storage/IMountServiceListener.aidl \
+	core/java/android/os/storage/IMountShutdownObserver.aidl \
 	core/java/android/os/INetworkManagementService.aidl \
 	core/java/android/os/INetStatService.aidl \
 	core/java/android/os/IPermissionController.aidl \
diff --git a/api/current.xml b/api/current.xml
index 21c1c18..ed3f6965 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -193450,6 +193450,17 @@
  visibility="public"
 >
 </method>
+<method name="getUseSystemOverscrollBackground"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getUseWideViewPort"
  return="boolean"
  abstract="false"
@@ -194029,6 +194040,19 @@
 <parameter name="use" type="boolean">
 </parameter>
 </method>
+<method name="setUseSystemOverscrollBackground"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="system" type="boolean">
+</parameter>
+</method>
 <method name="setUseWideViewPort"
  return="void"
  abstract="false"
diff --git a/cmds/servicemanager/Android.mk b/cmds/servicemanager/Android.mk
index 25266a2..392e727 100644
--- a/cmds/servicemanager/Android.mk
+++ b/cmds/servicemanager/Android.mk
@@ -10,5 +10,10 @@
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_SRC_FILES := service_manager.c binder.c
 LOCAL_MODULE := servicemanager
+ifeq ($(LVMX),true)
+  ifeq ($(TARGET_ARCH),arm)
+    LOCAL_CFLAGS += -DLVMX
+  endif
+endif
 include $(BUILD_EXECUTABLE)
 endif
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index f3a4713..a2006c1 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -27,6 +27,9 @@
     unsigned uid;
     const char *name;
 } allowed[] = {
+#ifdef LVMX
+    { AID_MEDIA, "com.lifevibes.mx.ipc" },
+#endif
     { AID_MEDIA, "media.audio_flinger" },
     { AID_MEDIA, "media.player" },
     { AID_MEDIA, "media.camera" },
diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java
index b3df522..5a79215 100644
--- a/core/java/android/os/Power.java
+++ b/core/java/android/os/Power.java
@@ -18,7 +18,6 @@
 
 import java.io.IOException;
 import android.os.ServiceManager;
-import android.os.storage.IMountService;
 
 /**
  * Class that provides access to some of the power management functions.
@@ -101,15 +100,6 @@
      */
     public static void reboot(String reason) throws IOException
     {
-        IMountService mSvc = IMountService.Stub.asInterface(
-                ServiceManager.getService("mount"));
-
-        if (mSvc != null) {
-            try {
-                mSvc.shutdown();
-            } catch (Exception e) {
-            }
-        }
         rebootNative(reason);
     }
 
diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl
index ad4cb10..75455ab 100644
--- a/core/java/android/os/storage/IMountService.aidl
+++ b/core/java/android/os/storage/IMountService.aidl
@@ -18,6 +18,7 @@
 package android.os.storage;
 
 import android.os.storage.IMountServiceListener;
+import android.os.storage.IMountShutdownObserver;
 
 /** WARNING! Update IMountService.h and IMountService.cpp if you change this file.
  * In particular, the ordering of the methods below must match the 
@@ -142,6 +143,7 @@
 
     /**
      * Shuts down the MountService and gracefully unmounts all external media.
+     * Invokes call back once the shutdown is complete.
      */
-    void shutdown();
+    void shutdown(IMountShutdownObserver observer);
 }
diff --git a/core/java/android/os/storage/IMountShutdownObserver.aidl b/core/java/android/os/storage/IMountShutdownObserver.aidl
new file mode 100644
index 0000000..0aa8a45
--- /dev/null
+++ b/core/java/android/os/storage/IMountShutdownObserver.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+/**
+ * Callback class for receiving events related
+ * to shutdown.
+ *
+ * @hide - For internal consumption only.
+ */
+interface IMountShutdownObserver {
+    /**
+     * This method is called when the shutdown
+     * of MountService completed.
+     * @param statusCode indicates success or failure
+     * of the shutdown.
+     */
+    void onShutDownComplete(int statusCode);
+}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 8981419..fb15f78 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -192,6 +192,7 @@
     private boolean         mBuiltInZoomControls = false;
     private boolean         mAllowFileAccess = true;
     private boolean         mLoadWithOverviewMode = false;
+    private boolean         mUseSystemOverscrollBackground = false;
 
     // private WebSettings, not accessible by the host activity
     static private int      mDoubleTapToastCount = 3;
@@ -470,6 +471,23 @@
     }
 
     /**
+     * Set whether the WebView uses system background for over scroll
+     * background. If false, it will use the WebView's background. Default is
+     * false.
+     */
+    public void setUseSystemOverscrollBackground(boolean system) {
+        mUseSystemOverscrollBackground = system;
+    }
+
+    /**
+     * Returns true if this WebView uses system background instead of WebView
+     * background for over scroll background.
+     */
+    public boolean getUseSystemOverscrollBackground() {
+        return mUseSystemOverscrollBackground;
+    }
+
+    /**
      * Store whether the WebView is saving form data.
      */
     public void setSaveFormData(boolean save) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 655c4c5..6f6ee1d 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2305,9 +2305,11 @@
             boolean clampedY) {
         mInOverScrollMode = false;
         int maxX = computeMaxScrollX();
-        if (Math.abs(mMinZoomScale - mMaxZoomScale) < 0.01f && maxX == 0) {
-            // do not over scroll x if the page can't be zoomed and it just fits
-            // the screen
+        if (maxX == 0 && (Math.abs(mMinZoomScale - mMaxZoomScale) < 0.01f)
+                || !getSettings().supportZoom()
+                || !getSettings().getUseWideViewPort()) {
+            // do not over scroll x if the page just fits the screen and it
+            // can't zoom or the view doesn't use wide viewport
             scrollX = pinLocX(scrollX);
         } else if (scrollX < 0 || scrollX > maxX) {
             mInOverScrollMode = true;
@@ -3112,7 +3114,8 @@
         }
 
         int saveCount = canvas.save();
-        if (mInOverScrollMode) {
+        if (mInOverScrollMode
+                && getSettings().getUseSystemOverscrollBackground()) {
             if (mOverScrollBackground == null) {
                 mOverScrollBackground = new Paint();
                 Bitmap bm = BitmapFactory.decodeResource(
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ae4d409..a1c3fa2 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1641,7 +1641,7 @@
                 mResurrectToPosition = mSelectedPosition;
             }
         } else {
-            if (mFiltered) {
+            if (mFiltered && !mPopupHidden) {
                 // Show the type filter only if a filter is in effect
                 showPopup();
             }
@@ -3510,7 +3510,6 @@
         if (mPopup != null) {
             mPopup.dismiss();
         }
-        mPopupHidden = false;
     }
 
     /**
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index 37898a1..51cd0f8 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -28,12 +28,13 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Handler;
+import android.os.Power;
 import android.os.PowerManager;
 import android.os.RemoteException;
-import android.os.Power;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.storage.IMountService;
+import android.os.storage.IMountShutdownObserver;
 
 import com.android.internal.telephony.ITelephony;
 import android.util.Log;
@@ -46,16 +47,20 @@
     private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500;
     // maximum time we wait for the shutdown broadcast before going on.
     private static final int MAX_BROADCAST_TIME = 10*1000;
+    private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
     
     // state tracking
     private static Object sIsStartedGuard = new Object();
     private static boolean sIsStarted = false;
     
+    private static boolean mReboot;
+    private static String mRebootReason;
+
     // static instance of this thread
     private static final ShutdownThread sInstance = new ShutdownThread();
     
-    private final Object mBroadcastDoneSync = new Object();
-    private boolean mBroadcastDone;
+    private final Object mActionDoneSync = new Object();
+    private boolean mActionDone;
     private Context mContext;
     private PowerManager mPowerManager;
     private PowerManager.WakeLock mWakeLock;
@@ -64,12 +69,13 @@
     private ShutdownThread() {
     }
  
-    /** 
+    /**
      * Request a clean shutdown, waiting for subsystems to clean up their
      * state etc.  Must be called from a Looper thread in which its UI
      * is shown.
-     * 
+     *
      * @param context Context used to display the shutdown progress dialog.
+     * @param confirm true if user confirmation is needed before shutting down.
      */
     public static void shutdown(final Context context, boolean confirm) {
         // ensure that only one thread is trying to power down.
@@ -106,6 +112,21 @@
         }
     }
 
+    /**
+     * Request a clean shutdown, waiting for subsystems to clean up their
+     * state etc.  Must be called from a Looper thread in which its UI
+     * is shown.
+     *
+     * @param context Context used to display the shutdown progress dialog.
+     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
+     * @param confirm true if user confirmation is needed before shutting down.
+     */
+    public static void reboot(final Context context, String reason, boolean confirm) {
+        mReboot = true;
+        mRebootReason = reason;
+        shutdown(context, confirm);
+    }
+
     private static void beginShutdownSequence(Context context) {
         synchronized (sIsStartedGuard) {
             sIsStarted = true;
@@ -145,13 +166,13 @@
         sInstance.start();
     }
 
-    void broadcastDone() {
-        synchronized (mBroadcastDoneSync) {
-            mBroadcastDone = true;
-            mBroadcastDoneSync.notifyAll();
+    void actionDone() {
+        synchronized (mActionDoneSync) {
+            mActionDone = true;
+            mActionDoneSync.notifyAll();
         }
     }
-    
+
     /**
      * Makes sure we handle the shutdown gracefully.
      * Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
@@ -163,27 +184,27 @@
         BroadcastReceiver br = new BroadcastReceiver() {
             @Override public void onReceive(Context context, Intent intent) {
                 // We don't allow apps to cancel this, so ignore the result.
-                broadcastDone();
+                actionDone();
             }
         };
         
         Log.i(TAG, "Sending shutdown broadcast...");
         
         // First send the high-level shut down broadcast.
-        mBroadcastDone = false;
+        mActionDone = false;
         mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), null,
                 br, mHandler, 0, null, null);
         
         final long endTime = System.currentTimeMillis() + MAX_BROADCAST_TIME;
-        synchronized (mBroadcastDoneSync) {
-            while (!mBroadcastDone) {
+        synchronized (mActionDoneSync) {
+            while (!mActionDone) {
                 long delay = endTime - System.currentTimeMillis();
                 if (delay <= 0) {
                     Log.w(TAG, "Shutdown broadcast timed out");
                     break;
                 }
                 try {
-                    mBroadcastDoneSync.wait(delay);
+                    mActionDoneSync.wait(delay);
                 } catch (InterruptedException e) {
                 }
             }
@@ -262,17 +283,50 @@
         }
 
         // Shutdown MountService to ensure media is in a safe state
-        try {
-            if (mount != null) {
-                mount.shutdown();
-            } else {
-                Log.w(TAG, "MountService unavailable for shutdown");
+        IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
+            public void onShutDownComplete(int statusCode) throws RemoteException {
+                Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown");
+                actionDone();
             }
-        } catch (Exception e) {
-            Log.e(TAG, "Exception during MountService shutdown", e);
+        };
+
+        Log.i(TAG, "Shutting down MountService");
+        // Set initial variables and time out time.
+        mActionDone = false;
+        final long endShutTime = System.currentTimeMillis() + MAX_SHUTDOWN_WAIT_TIME;
+        synchronized (mActionDoneSync) {
+            try {
+                if (mount != null) {
+                    mount.shutdown(observer);
+                } else {
+                    Log.w(TAG, "MountService unavailable for shutdown");
+                }
+            } catch (Exception e) {
+                Log.e(TAG, "Exception during MountService shutdown", e);
+            }
+            while (!mActionDone) {
+                long delay = endShutTime - System.currentTimeMillis();
+                if (delay <= 0) {
+                    Log.w(TAG, "Shutdown wait timed out");
+                    break;
+                }
+                try {
+                    mActionDoneSync.wait(delay);
+                } catch (InterruptedException e) {
+                }
+            }
         }
 
-        //shutdown power
+        if (mReboot) {
+            Log.i(TAG, "Rebooting, reason: " + mRebootReason);
+            try {
+                Power.reboot(mRebootReason);
+            } catch (Exception e) {
+                Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
+            }
+        }
+
+        // Shutdown power
         Log.i(TAG, "Performing low-level shutdown...");
         Power.shutdown();
     }
diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk
index b68bfc1..29e4a57 100644
--- a/libs/audioflinger/Android.mk
+++ b/libs/audioflinger/Android.mk
@@ -24,7 +24,7 @@
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libutils \
-	libbinder \
+    libbinder \
     libmedia \
     libhardware_legacy
 
@@ -85,7 +85,7 @@
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libutils \
-	libbinder \
+    libbinder \
     libmedia \
     libhardware_legacy
 
@@ -114,9 +114,19 @@
 endif
 
 ifeq ($(TARGET_SIMULATOR),true)
-	ifeq ($(HOST_OS),linux)
-		LOCAL_LDLIBS += -lrt -lpthread
-	endif
+    ifeq ($(HOST_OS),linux)
+        LOCAL_LDLIBS += -lrt -lpthread
+    endif
+endif
+
+ifeq ($(LVMX),true)
+  ifeq ($(TARGET_ARCH),arm)
+    LOCAL_CFLAGS += -DLVMX
+    LOCAL_C_INCLUDES += vendor/nxp
+    LOCAL_STATIC_LIBRARIES += liblifevibes
+    LOCAL_SHARED_LIBRARIES += liblvmxservice
+#    LOCAL_SHARED_LIBRARIES += liblvmxipc
+  endif
 endif
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 8089389..7902212 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -47,6 +47,10 @@
 #include "A2dpAudioInterface.h"
 #endif
 
+#ifdef LVMX
+#include "lifevibes.h"
+#endif
+
 // ----------------------------------------------------------------------------
 // the sim build doesn't have gettid
 
@@ -132,6 +136,9 @@
     } else {
         LOGE("Couldn't even initialize the stubbed audio hardware!");
     }
+#ifdef LVMX
+    LifeVibes::init();
+#endif
 }
 
 AudioFlinger::~AudioFlinger()
@@ -411,6 +418,11 @@
     AutoMutex lock(mHardwareLock);
     mHardwareStatus = AUDIO_HW_SET_MODE;
     status_t ret = mAudioHardware->setMode(mode);
+#ifdef LVMX
+    if (NO_ERROR == ret) {
+        LifeVibes::setMode(mode);
+    }
+#endif
     mHardwareStatus = AUDIO_HW_IDLE;
     return ret;
 }
@@ -566,11 +578,37 @@
         return PERMISSION_DENIED;
     }
 
+#ifdef LVMX
+    AudioParameter param = AudioParameter(keyValuePairs);
+    LifeVibes::setParameters(ioHandle,keyValuePairs);
+    String8 key = String8(AudioParameter::keyRouting);
+    int device;
+    if (NO_ERROR != param.getInt(key, device)) {
+        device = -1;
+    }
+
+    key = String8(LifevibesTag);
+    String8 value;
+    int musicEnabled = -1;
+    if (NO_ERROR == param.get(key, value)) {
+        if (value == LifevibesEnable) {
+            musicEnabled = 1;
+        } else if (value == LifevibesDisable) {
+            musicEnabled = 0;
+        }
+    }
+#endif
+
     // ioHandle == 0 means the parameters are global to the audio hardware interface
     if (ioHandle == 0) {
         AutoMutex lock(mHardwareLock);
         mHardwareStatus = AUDIO_SET_PARAMETER;
         result = mAudioHardware->setParameters(keyValuePairs);
+#ifdef LVMX
+        if ((NO_ERROR == result) && (musicEnabled != -1)) {
+            LifeVibes::enableMusic((bool) musicEnabled);
+        }
+#endif
         mHardwareStatus = AUDIO_HW_IDLE;
         return result;
     }
@@ -586,7 +624,13 @@
         }
     }
     if (thread != NULL) {
-        return thread->setParameters(keyValuePairs);
+        result = thread->setParameters(keyValuePairs);
+#ifdef LVMX
+        if ((NO_ERROR == result) && (device != -1)) {
+            LifeVibes::setDevice(LifeVibes::threadIdToAudioOutputType(thread->id()), device);
+        }
+#endif
+        return result;
     }
     return BAD_VALUE;
 }
@@ -1058,12 +1102,24 @@
 
 status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
 {
+#ifdef LVMX
+    int audioOutputType = LifeVibes::getMixerType(mId, mType);
+    if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
+        LifeVibes::setMasterVolume(audioOutputType, value);
+    }
+#endif
     mMasterVolume = value;
     return NO_ERROR;
 }
 
 status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
 {
+#ifdef LVMX
+    int audioOutputType = LifeVibes::getMixerType(mId, mType);
+    if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
+        LifeVibes::setMasterMute(audioOutputType, muted);
+    }
+#endif
     mMasterMute = muted;
     return NO_ERROR;
 }
@@ -1080,12 +1136,24 @@
 
 status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
 {
+#ifdef LVMX
+    int audioOutputType = LifeVibes::getMixerType(mId, mType);
+    if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
+        LifeVibes::setStreamVolume(audioOutputType, stream, value);
+    }
+#endif
     mStreamTypes[stream].volume = value;
     return NO_ERROR;
 }
 
 status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
 {
+#ifdef LVMX
+    int audioOutputType = LifeVibes::getMixerType(mId, mType);
+    if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
+        LifeVibes::setStreamMute(audioOutputType, stream, muted);
+    }
+#endif
     mStreamTypes[stream].mute = muted;
     return NO_ERROR;
 }
@@ -1333,6 +1401,12 @@
             mLastWriteTime = systemTime();
             mInWrite = true;
             mBytesWritten += mixBufferSize;
+#ifdef LVMX
+            int audioOutputType = LifeVibes::getMixerType(mId, mType);
+            if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
+               LifeVibes::process(audioOutputType, curBuf, mixBufferSize);
+            }
+#endif
             int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
             if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
             mNumWrites++;
@@ -1376,6 +1450,29 @@
     uint32_t mixerStatus = MIXER_IDLE;
     // find out which tracks need to be processed
     size_t count = activeTracks.size();
+
+    float masterVolume = mMasterVolume;
+    bool  masterMute = mMasterMute;
+
+#ifdef LVMX
+    bool tracksConnectedChanged = false;
+    bool stateChanged = false;
+
+    int audioOutputType = LifeVibes::getMixerType(mId, mType);
+    if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
+    {
+        int activeTypes = 0;
+        for (size_t i=0 ; i<count ; i++) {
+            sp<Track> t = activeTracks[i].promote();
+            if (t == 0) continue;
+            Track* const track = t.get();
+            int iTracktype=track->type();
+            activeTypes |= 1<<track->type();
+        }
+        LifeVibes::computeVolumes(audioOutputType, activeTypes, tracksConnectedChanged, stateChanged, masterVolume, masterMute);
+    }
+#endif
+
     for (size_t i=0 ; i<count ; i++) {
         sp<Track> t = activeTracks[i].promote();
         if (t == 0) continue;
@@ -1393,15 +1490,27 @@
 
             // compute volume for this track
             int16_t left, right;
-            if (track->isMuted() || mMasterMute || track->isPausing() ||
+            if (track->isMuted() || masterMute || track->isPausing() ||
                 mStreamTypes[track->type()].mute) {
                 left = right = 0;
                 if (track->isPausing()) {
                     track->setPaused();
                 }
             } else {
+                // read original volumes with volume control
                 float typeVolume = mStreamTypes[track->type()].volume;
-                float v = mMasterVolume * typeVolume;
+#ifdef LVMX
+                bool streamMute=false;
+                // read the volume from the LivesVibes audio engine.
+                if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
+                {
+                    LifeVibes::getStreamVolumes(audioOutputType, track->type(), &typeVolume, &streamMute);
+                    if (streamMute) {
+                        typeVolume = 0;
+                    }
+                }
+#endif
+                float v = masterVolume * typeVolume;
                 float v_clamped = v * cblk->volume[0];
                 if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
                 left = int16_t(v_clamped);
@@ -1427,7 +1536,13 @@
                 // do not apply ramp
                 param = AudioMixer::RAMP_VOLUME;
             }
-
+#ifdef LVMX
+            if ( tracksConnectedChanged || stateChanged )
+            {
+                 // only do the ramp when the volume is changed by the user / application
+                 param = AudioMixer::VOLUME;
+            }
+#endif
             mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
             mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
             mAudioMixer->setParameter(
@@ -3652,6 +3767,18 @@
         } else {
             thread = new MixerThread(this, output, ++mNextThreadId);
             LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread);
+
+#ifdef LVMX
+            unsigned bitsPerSample =
+                (format == AudioSystem::PCM_16_BIT) ? 16 :
+                    ((format == AudioSystem::PCM_8_BIT) ? 8 : 0);
+            unsigned channelCount = (channels == AudioSystem::CHANNEL_OUT_STEREO) ? 2 : 1;
+            int audioOutputType = LifeVibes::threadIdToAudioOutputType(thread->id());
+
+            LifeVibes::init_aot(audioOutputType, samplingRate, bitsPerSample, channelCount);
+            LifeVibes::setDevice(audioOutputType, *pDevices);
+#endif
+
         }
         mPlaybackThreads.add(mNextThreadId, thread);
 
diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp
index ae215d1..d481150 100644
--- a/libs/audioflinger/AudioHardwareStub.cpp
+++ b/libs/audioflinger/AudioHardwareStub.cpp
@@ -166,7 +166,7 @@
 // ----------------------------------------------------------------------------
 
 status_t AudioStreamInStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate,
-				AudioSystem::audio_in_acoustics acoustics)
+                AudioSystem::audio_in_acoustics acoustics)
 {
     return NO_ERROR;
 }
diff --git a/libs/audioflinger/AudioResampler.h b/libs/audioflinger/AudioResampler.h
index 39656c0..2dfac76 100644
--- a/libs/audioflinger/AudioResampler.h
+++ b/libs/audioflinger/AudioResampler.h
@@ -76,8 +76,8 @@
     int32_t mInSampleRate;
     AudioBufferProvider::Buffer mBuffer;
     union {
-    	int16_t mVolume[2];
-    	uint32_t mVolumeRL;
+        int16_t mVolume[2];
+        uint32_t mVolumeRL;
     };
     int16_t mTargetVolume[2];
     format mFormat;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index a1c45dc..70deb3e 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -995,6 +995,8 @@
                     }
                 } else {
                     newNet.reconnect();
+                    newNet = null; // not officially avail..  try anyway, but
+                                   // report no failover
                 }
             }
         }
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 0974f7f..713358d 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -26,6 +26,7 @@
 import android.net.Uri;
 import android.os.storage.IMountService;
 import android.os.storage.IMountServiceListener;
+import android.os.storage.IMountShutdownObserver;
 import android.os.storage.StorageResultCode;
 import android.os.Handler;
 import android.os.Message;
@@ -172,69 +173,110 @@
         }
     }
 
+    class ShutdownCallBack extends UnmountCallBack {
+        IMountShutdownObserver observer;
+        ShutdownCallBack(String path, IMountShutdownObserver observer) {
+            super(path, true);
+            this.observer = observer;
+        }
+
+        @Override
+        void handleFinished() {
+            int ret = doUnmountVolume(path, true);
+            if (observer != null) {
+                try {
+                    observer.onShutDownComplete(ret);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "RemoteException when shutting down");
+                }
+            }
+        }
+    }
+
     final private Handler mHandler = new Handler() {
         ArrayList<UnmountCallBack> mForceUnmounts = new ArrayList<UnmountCallBack>();
+        boolean mRegistered = false;
+
+        void registerReceiver() {
+            mRegistered = true;
+            mContext.registerReceiver(mPmReceiver, mPmFilter);
+        }
+
+        void unregisterReceiver() {
+            mRegistered = false;
+            mContext.unregisterReceiver(mPmReceiver);
+        }
 
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case H_UNMOUNT_PM_UPDATE: {
                     UnmountCallBack ucb = (UnmountCallBack) msg.obj;
                     mForceUnmounts.add(ucb);
-                    mContext.registerReceiver(mPmReceiver, mPmFilter);
-                    boolean hasExtPkgs = mPms.updateExternalMediaStatus(false);
-                    if (!hasExtPkgs) {
-                        // Unregister right away
-                        mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE);
+                    // Register only if needed.
+                    if (!mRegistered) {
+                        registerReceiver();
+                        boolean hasExtPkgs = mPms.updateExternalMediaStatus(false);
+                        if (!hasExtPkgs) {
+                            // Unregister right away
+                            mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE);
+                        }
                     }
                     break;
                 }
                 case H_UNMOUNT_PM_DONE: {
-                    // Unregister receiver
-                    mContext.unregisterReceiver(mPmReceiver);
-                    UnmountCallBack ucb = mForceUnmounts.get(0);
-                    if (ucb == null || ucb.path == null) {
-                        // Just ignore
-                        return;
+                    // Unregister now.
+                    if (mRegistered) {
+                        unregisterReceiver();
                     }
-                    String path = ucb.path;
-                    boolean done = false;
-                    if (!ucb.force) {
-                        done = true;
-                    } else {
-                        int pids[] = getStorageUsers(path);
-                        if (pids == null || pids.length == 0) {
+                    int size = mForceUnmounts.size();
+                    int sizeArr[] = new int[size];
+                    int sizeArrN = 0;
+                    for (int i = 0; i < size; i++) {
+                        UnmountCallBack ucb = mForceUnmounts.get(i);
+                        String path = ucb.path;
+                        boolean done = false;
+                        if (!ucb.force) {
                             done = true;
                         } else {
-                            // Kill processes holding references first
-                            ActivityManagerService ams = (ActivityManagerService)
-                            ServiceManager.getService("activity");
-                            // Eliminate system process here?
-                            boolean ret = ams.killPidsForMemory(pids);
-                            if (ret) {
-                                // Confirm if file references have been freed.
-                                pids = getStorageUsers(path);
-                                if (pids == null || pids.length == 0) {
-                                    done = true;
+                            int pids[] = getStorageUsers(path);
+                            if (pids == null || pids.length == 0) {
+                                done = true;
+                            } else {
+                                // Kill processes holding references first
+                                ActivityManagerService ams = (ActivityManagerService)
+                                ServiceManager.getService("activity");
+                                // Eliminate system process here?
+                                boolean ret = ams.killPidsForMemory(pids);
+                                if (ret) {
+                                    // Confirm if file references have been freed.
+                                    pids = getStorageUsers(path);
+                                    if (pids == null || pids.length == 0) {
+                                        done = true;
+                                    }
                                 }
                             }
                         }
-                    }
-                    if (done) {
-                        mForceUnmounts.remove(0);
-                        mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_MS,
-                                ucb));
-                    } else {
-                        if (ucb.retries >= MAX_UNMOUNT_RETRIES) {
-                            Log.i(TAG, "Cannot unmount inspite of " +
-                                    MAX_UNMOUNT_RETRIES + " to unmount media");
-                            // Send final broadcast indicating failure to unmount.                      
+                        if (done) {
+                            sizeArr[sizeArrN++] = i;
+                            mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_MS,
+                                    ucb));
                         } else {
-                            mHandler.sendMessageDelayed(
-                                    mHandler.obtainMessage(H_UNMOUNT_PM_DONE,
-                                            ucb.retries++),
-                                    RETRY_UNMOUNT_DELAY);
+                            if (ucb.retries >= MAX_UNMOUNT_RETRIES) {
+                                Log.i(TAG, "Cannot unmount inspite of " +
+                                        MAX_UNMOUNT_RETRIES + " to unmount media");
+                                // Send final broadcast indicating failure to unmount.                 
+                            } else {
+                                mHandler.sendMessageDelayed(
+                                        mHandler.obtainMessage(H_UNMOUNT_PM_DONE,
+                                                ucb.retries++),
+                                        RETRY_UNMOUNT_DELAY);
+                            }
                         }
                     }
+                    // Remove already processed elements from list.
+                    for (int i = (sizeArrN-1); i >= 0; i--) {
+                        mForceUnmounts.remove(sizeArr[i]);
+                    }
                     break;
                 }
                 case H_UNMOUNT_MS : {
@@ -826,7 +868,7 @@
         }
     }
 
-    public void shutdown() {
+    public void shutdown(final IMountShutdownObserver observer) {
         validatePermission(android.Manifest.permission.SHUTDOWN);
 
         Log.i(TAG, "Shutting down");
@@ -865,12 +907,9 @@
         }
 
         if (state.equals(Environment.MEDIA_MOUNTED)) {
-            /*
-             * If the media is mounted, then gracefully unmount it.
-             */
-            if (doUnmountVolume(path, true) != StorageResultCode.OperationSucceeded) {
-                Log.e(TAG, "Failed to unmount media for shutdown");
-            }
+            // Post a unmount message.
+            ShutdownCallBack ucb = new ShutdownCallBack(path, observer);
+            mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb));
         }
     }
 
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 0189c60..fc6bfcd 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import com.android.internal.app.IBatteryStats;
+import com.android.internal.app.ShutdownThread;
 import com.android.server.am.BatteryStatsService;
 
 import android.app.ActivityManagerNative;
@@ -41,7 +42,6 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
-import android.os.storage.IMountService;
 import android.os.IPowerManager;
 import android.os.LocalPowerManager;
 import android.os.Power;
@@ -2202,28 +2202,35 @@
     {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
 
-        /*
-         * Manually shutdown the MountService to ensure media is
-         * put into a safe state.
-         */
-        IMountService mSvc = IMountService.Stub.asInterface(
-                ServiceManager.getService("mount"));
-
-        if (mSvc != null) {
-            try {
-                mSvc.shutdown();
-            } catch (Exception e) {
-                Slog.e(TAG, "MountService shutdown failed", e);
+        if (mHandler == null || !ActivityManagerNative.isSystemReady()) {
+            throw new IllegalStateException("Too early to call reboot()");
+        }
+        
+        final String finalReason = reason;
+        Runnable runnable = new Runnable() {
+            public void run() {
+                synchronized (this) {
+                    ShutdownThread.reboot(mContext, finalReason, false);
+                    // if we get here we failed
+                    notify();
+                }
+                
             }
-        } else {
-            Slog.w(TAG, "MountService unavailable for shutdown");
-        }
+        };
 
-        try {
-            Power.reboot(reason);
-        } catch (IOException e) {
-            Slog.e(TAG, "reboot failed", e);
+        mHandler.post(runnable);
+
+        // block until we reboot or fail.
+        // throw an exception if we failed to reboot
+        synchronized (runnable) {
+            try {
+                runnable.wait();
+            } catch (InterruptedException e) {
+            }
         }
+     
+        // if we get here we failed
+        throw new IllegalStateException("unable to reboot!");
     }
 
     /**
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index f97f50a..3f64b25 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -29,6 +29,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.Process;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
@@ -676,11 +677,8 @@
      */
     void rebootSystem(String reason) {
         Slog.i(TAG, "Rebooting system because: " + reason);
-        try {
-            android.os.Power.reboot(reason);
-        } catch (IOException e) {
-            Slog.e(TAG, "Reboot failed!", e);
-        }
+        PowerManagerService pms = (PowerManagerService) ServiceManager.getService("power");
+        pms.reboot(reason);
     }
 
     /**
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index f5d3e8e..34a7fc0 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -10267,9 +10267,10 @@
                                 && buttonBrightness < 0) {
                             buttonBrightness = w.mAttrs.buttonBrightness;
                         }
-                        if (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
-                                || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
-                                || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR) {
+                        if (canBeSeen
+                                && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
+                                 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
+                                 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) {
                             syswin = true;
                         }
                     }
diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml
index e06c3a8..1f0bf4d 100644
--- a/tests/AndroidTests/AndroidManifest.xml
+++ b/tests/AndroidTests/AndroidManifest.xml
@@ -35,6 +35,7 @@
     <uses-permission android:name="android.permission.ASEC_DESTROY" />
     <uses-permission android:name="android.permission.ASEC_MOUNT_UNMOUNT" />
     <uses-permission android:name="android.permission.ASEC_RENAME" />
+    <uses-permission android:name="android.permission.SHUTDOWN" />
     <uses-permission android:name="com.android.unit_tests.permission.TEST_GRANTED" />
     <uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" />
     <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
diff --git a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
index c7bacd4..9aed363 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
@@ -16,6 +16,8 @@
 
 package com.android.unit_tests;
 
+import com.android.unit_tests.PackageManagerTests.StorageListener;
+
 import android.os.storage.IMountService.Stub;
 
 import android.net.Uri;
@@ -41,6 +43,9 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.storage.IMountService;
+import android.os.storage.IMountShutdownObserver;
+import android.os.storage.StorageEventListener;
+import android.os.storage.StorageManager;
 import android.os.storage.StorageResultCode;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -365,4 +370,256 @@
         }
     }
 
+    /*------------ Tests for unmounting volume ---*/
+    public final long MAX_WAIT_TIME=120*1000;
+    public final long WAIT_TIME_INCR=20*1000;
+    boolean getMediaState() {
+        try {
+        String mPath = Environment.getExternalStorageDirectory().toString();
+        String state = getMs().getVolumeState(mPath);
+        return Environment.MEDIA_MOUNTED.equals(state);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    boolean mountMedia() {
+        if (getMediaState()) {
+            return true;
+        }
+        try {
+        String mPath = Environment.getExternalStorageDirectory().toString();
+        int ret = getMs().mountVolume(mPath);
+        return ret == StorageResultCode.OperationSucceeded;
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    class StorageListener extends StorageEventListener {
+        String oldState;
+        String newState;
+        String path;
+        private boolean doneFlag = false;
+
+        public void action() {
+            synchronized (this) {
+                doneFlag = true;
+                notifyAll();
+            }
+        }
+
+        public boolean isDone() {
+            return doneFlag;
+        }
+
+        @Override
+        public void onStorageStateChanged(String path, String oldState, String newState) {
+            if (localLOGV) Log.i(TAG, "Storage state changed from " + oldState + " to " + newState);
+            this.oldState = oldState;
+            this.newState = newState;
+            this.path = path;
+            action();
+        }
+    }
+
+    private boolean unmountMedia() {
+        if (!getMediaState()) {
+            return true;
+        }
+        String path = Environment.getExternalStorageDirectory().toString();
+        StorageListener observer = new StorageListener();
+        StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
+        sm.registerListener(observer);
+        try {
+            // Wait on observer
+            synchronized(observer) {
+                getMs().unmountVolume(path, false);
+                long waitTime = 0;
+                while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                    observer.wait(WAIT_TIME_INCR);
+                    waitTime += WAIT_TIME_INCR;
+                }
+                if(!observer.isDone()) {
+                    throw new Exception("Timed out waiting for packageInstalled callback");
+                }
+                return true;
+            }
+        } catch (Exception e) {
+            return false;
+        } finally {
+            sm.unregisterListener(observer);
+        }
+    }
+    public void testUnmount() {
+        boolean oldStatus = getMediaState();
+        Log.i(TAG, "oldStatus="+oldStatus);
+        try {
+            // Mount media firsts
+            if (!getMediaState()) {
+                mountMedia();
+            }
+            assertTrue(unmountMedia());
+        } finally {
+            // Restore old status
+            boolean currStatus = getMediaState();
+            if (oldStatus != currStatus) {
+                if (oldStatus) {
+                    // Mount media
+                    mountMedia();
+                } else {
+                    unmountMedia();
+                }
+            }
+        }
+    }
+
+    class MultipleStorageLis extends StorageListener {
+        int count = 0;
+        public void onStorageStateChanged(String path, String oldState, String newState) {
+            count++;
+            super.action();
+        }
+    }
+    /*
+     * This test invokes unmount multiple time and expects the call back
+     * to be invoked just once.
+     */
+    public void testUnmountMultiple() {
+        boolean oldStatus = getMediaState();
+        StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
+        MultipleStorageLis observer = new MultipleStorageLis();
+        try {
+            // Mount media firsts
+            if (!getMediaState()) {
+                mountMedia();
+            }
+            String path = Environment.getExternalStorageDirectory().toString();
+            sm.registerListener(observer);
+            // Wait on observer
+            synchronized(observer) {
+                for (int i = 0; i < 5; i++) {
+                    getMs().unmountVolume(path, false);
+                }
+                long waitTime = 0;
+                while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                    observer.wait(WAIT_TIME_INCR);
+                    waitTime += WAIT_TIME_INCR;
+                }
+                if(!observer.isDone()) {
+                    failStr("Timed out waiting for packageInstalled callback");
+                }
+            }
+            assertEquals(observer.count, 1);
+        } catch (Exception e) {
+            failStr(e);
+        } finally {
+            sm.unregisterListener(observer);
+            // Restore old status
+            boolean currStatus = getMediaState();
+            if (oldStatus != currStatus) {
+                if (oldStatus) {
+                    // Mount media
+                    mountMedia();
+                } else {
+                    unmountMedia();
+                }
+            }
+        }
+    }
+    
+    class ShutdownObserver extends  IMountShutdownObserver.Stub{
+        private boolean doneFlag = false;
+        int statusCode;
+
+        public void action() {
+            synchronized (this) {
+                doneFlag = true;
+                notifyAll();
+            }
+        }
+
+        public boolean isDone() {
+            return doneFlag;
+        }
+        public void onShutDownComplete(int statusCode) throws RemoteException {
+            this.statusCode = statusCode;
+            action();
+        }
+        
+    }
+
+    boolean invokeShutdown() {
+        IMountService ms = getMs();
+        ShutdownObserver observer = new ShutdownObserver();
+        synchronized (observer) {
+            try {
+                ms.shutdown(observer);
+                return true;
+            } catch (RemoteException e) {
+                failStr(e);
+            }
+        }
+        return false;
+    }
+
+    public void testShutdown() {
+        boolean oldStatus = getMediaState();
+        try {
+            // Mount media firsts
+            if (!getMediaState()) {
+                mountMedia();
+            }
+            assertTrue(invokeShutdown());
+        } finally {
+            // Restore old status
+            boolean currStatus = getMediaState();
+            if (oldStatus != currStatus) {
+                if (oldStatus) {
+                    // Mount media
+                    mountMedia();
+                } else {
+                    unmountMedia();
+                }
+            }
+        }
+    }
+
+    /*
+     * This test invokes unmount multiple time and expects the call back
+     * to be invoked just once.
+     */
+    public void testShutdownMultiple() {
+        boolean oldStatus = getMediaState();
+        try {
+            // Mount media firsts
+            if (!getMediaState()) {
+                mountMedia();
+            }
+            IMountService ms = getMs();
+            ShutdownObserver observer = new ShutdownObserver();
+            synchronized (observer) {
+                try {
+                    ms.shutdown(observer);
+                    for (int i = 0; i < 4; i++) {
+                        ms.shutdown(null);
+                    }
+                } catch (RemoteException e) {
+                    failStr(e);
+                }
+            }
+        } finally {
+            // Restore old status
+            boolean currStatus = getMediaState();
+            if (oldStatus != currStatus) {
+                if (oldStatus) {
+                    // Mount media
+                    mountMedia();
+                } else {
+                    unmountMedia();
+                }
+            }
+        }
+    }
+
 }