Merge "Make the silent/vibrate status icon reflect overall device state. (DO NOT MERGE)" into froyo
diff --git a/Android.mk b/Android.mk
index 10b6d67..8783934 100644
--- a/Android.mk
+++ b/Android.mk
@@ -369,6 +369,7 @@
     -since ./frameworks/base/api/5.xml 5 \
     -since ./frameworks/base/api/6.xml 6 \
     -since ./frameworks/base/api/7.xml 7 \
+    -since ./frameworks/base/api/8.xml 8 \
 		-error 1 -error 2 -warning 3 -error 4 -error 6 -error 8 \
 		-overview $(LOCAL_PATH)/core/java/overview.html
 
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index dc0d864..0e8b665 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -534,9 +534,11 @@
                 .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE))
                 .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE))
                 .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE))
-                .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE))
-                .appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE))
-                .appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE))
+                .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE));
+        if ((mVCardType & VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT) == 0) {
+            builder.appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE));
+        }
+        builder.appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE))
                 .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE))
                 .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE))
                 .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE));
diff --git a/core/java/android/pim/vcard/VCardConfig.java b/core/java/android/pim/vcard/VCardConfig.java
index 3442ae7..3409be6 100644
--- a/core/java/android/pim/vcard/VCardConfig.java
+++ b/core/java/android/pim/vcard/VCardConfig.java
@@ -182,6 +182,14 @@
      */
     public static final int FLAG_APPEND_TYPE_PARAM = 0x04000000;
 
+    /**
+     * <P>
+     * The flag asking exporter to refrain image export.
+     * </P>
+     * @hide will be deleted in the near future.
+     */
+    public static final int FLAG_REFRAIN_IMAGE_EXPORT = 0x02000000;
+
     //// The followings are VCard types available from importer/exporter. ////
 
     /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d99ebc9..11e5ad1 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1512,6 +1512,13 @@
      * @hide
      */
     static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
+    
+    /**
+     * Indicates that we should awaken scroll bars once attached
+     * 
+     * @hide
+     */
+    private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
 
     /**
      * The parent this view is attached to.
@@ -3838,6 +3845,13 @@
      * {@link #INVISIBLE} or {@link #GONE}.
      */
     protected void onVisibilityChanged(View changedView, int visibility) {
+        if (visibility == VISIBLE) {
+            if (mAttachInfo != null) {
+                initialAwakenScrollBars();
+            } else {
+                mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
+            }
+        }
     }
 
     /**
@@ -3888,6 +3902,9 @@
      * @param visibility The new visibility of the window.
      */
     protected void onWindowVisibilityChanged(int visibility) {
+        if (visibility == VISIBLE) {
+            initialAwakenScrollBars();
+        }
     }
 
     /**
@@ -4909,6 +4926,19 @@
     }
 
     /**
+     * Trigger the scrollbars to draw.
+     * This method differs from awakenScrollBars() only in its default duration.
+     * initialAwakenScrollBars() will show the scroll bars for longer than
+     * usual to give the user more of a chance to notice them.
+     *
+     * @return true if the animation is played, false otherwise.
+     */
+    private boolean initialAwakenScrollBars() {
+        return mScrollCache != null &&
+                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
+    }
+
+    /**
      * <p>
      * Trigger the scrollbars to draw. When invoked this method starts an
      * animation to fade the scrollbars out after a fixed delay. If a subclass
@@ -5900,6 +5930,10 @@
         if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
             mParent.requestTransparentRegion(this);
         }
+        if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
+            initialAwakenScrollBars();
+            mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
+        }
     }
 
     /**
diff --git a/core/java/android/webkit/PluginFullScreenHolder.java b/core/java/android/webkit/PluginFullScreenHolder.java
index 6d9e108..ae326d5 100644
--- a/core/java/android/webkit/PluginFullScreenHolder.java
+++ b/core/java/android/webkit/PluginFullScreenHolder.java
@@ -27,6 +27,7 @@
 import android.app.Dialog;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.SurfaceView;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -51,6 +52,16 @@
         contentView.setLayoutParams(new ViewGroup.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT));
+        // fixed size is only used either during pinch zoom or surface is too
+        // big. Make sure it is not fixed size before setting it to the full
+        // screen content view. The SurfaceView will be set to the correct mode
+        // by the ViewManager when it is re-attached to the WebView.
+        if (contentView instanceof SurfaceView) {
+            final SurfaceView sView = (SurfaceView) contentView;
+            if (sView.isFixedSize()) {
+                sView.getHolder().setSizeFromLayout();
+            }
+        }
         super.setContentView(contentView);
         mContentView = contentView;
     }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6db974c..ff233d2 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -874,18 +874,18 @@
     }
 
     private void updateZoomButtonsEnabled() {
+        if (mZoomButtonsController == null) return;
         boolean canZoomIn = mActualScale < mMaxZoomScale;
         boolean canZoomOut = mActualScale > mMinZoomScale && !mInZoomOverview;
-        ZoomButtonsController controller = getZoomButtonsController();
         if (!canZoomIn && !canZoomOut) {
             // Hide the zoom in and out buttons, as well as the fit to page
             // button, if the page cannot zoom
-            controller.getZoomControls().setVisibility(View.GONE);
+            mZoomButtonsController.getZoomControls().setVisibility(View.GONE);
         } else {
             // Set each one individually, as a page may be able to zoom in
             // or out.
-            controller.setZoomInEnabled(canZoomIn);
-            controller.setZoomOutEnabled(canZoomOut);
+            mZoomButtonsController.setZoomInEnabled(canZoomIn);
+            mZoomButtonsController.setZoomOutEnabled(canZoomOut);
         }
     }
 
@@ -4013,7 +4013,8 @@
             }
         } else {
             if (mWebViewCore != null && getSettings().getBuiltInZoomControls()
-                    && !getZoomButtonsController().isVisible()) {
+                    && (mZoomButtonsController == null ||
+                            !mZoomButtonsController.isVisible())) {
                 /*
                  * The zoom controls come in their own window, so our window
                  * loses focus. Our policy is to not draw the cursor ring if
@@ -4939,6 +4940,11 @@
                                 WebViewCore.pauseUpdatePicture(mWebViewCore);
                                 // fall through to TOUCH_DRAG_MODE
                             } else {
+                                // WebKit may consume the touch event and modify
+                                // DOM. drawContentPicture() will be called with
+                                // animateSroll as true for better performance.
+                                // Force redraw in high-quality.
+                                invalidate();
                                 break;
                             }
                         } else {
@@ -5837,7 +5843,7 @@
         }
         WebSettings settings = getSettings();
         if (settings.getBuiltInZoomControls()) {
-            if (getZoomButtonsController().isVisible()) {
+            if (mZoomButtonsController != null) {
                 mZoomButtonsController.setVisible(false);
             }
         } else {
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 6660c276..9fbf171 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -712,15 +712,6 @@
       mOptions.add(opt);
     }
 
-    char lockProfSampleBuf[sizeof("-Xlockprofsample:") + sizeof(propBuf)];
-    property_get("dalvik.vm.lockprof.sample", propBuf, "");
-    if (strlen(propBuf) > 0) {
-      strcpy(lockProfSampleBuf, "-Xlockprofsample:");
-      strcat(lockProfSampleBuf, propBuf);
-      opt.optionString = lockProfSampleBuf;
-      mOptions.add(opt);
-    }
-
 #if defined(WITH_JIT)
     /* Minimal profile threshold to trigger JIT compilation */
     char jitThresholdBuf[sizeof("-Xjitthreshold:") + PROPERTY_VALUE_MAX];
diff --git a/include/binder/IMemory.h b/include/binder/IMemory.h
index ae042cb..74d2cc7 100644
--- a/include/binder/IMemory.h
+++ b/include/binder/IMemory.h
@@ -36,8 +36,7 @@
 
     // flags returned by getFlags()
     enum {
-        READ_ONLY   = 0x00000001,
-        MAP_ONCE    = 0x00000002
+        READ_ONLY   = 0x00000001
     };
 
     virtual int         getHeapID() const = 0;
diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
index d793c24..2f2e31b 100644
--- a/include/binder/MemoryHeapBase.h
+++ b/include/binder/MemoryHeapBase.h
@@ -32,7 +32,6 @@
 public:
     enum {
         READ_ONLY = IMemoryHeap::READ_ONLY,
-        MAP_ONCE = IMemoryHeap::MAP_ONCE,
         // memory won't be mapped locally, but will be mapped in the remote
         // process.
         DONT_MAP_LOCALLY = 0x00000100,
diff --git a/include/binder/MemoryHeapPmem.h b/include/binder/MemoryHeapPmem.h
index aac164f..e1660c4 100644
--- a/include/binder/MemoryHeapPmem.h
+++ b/include/binder/MemoryHeapPmem.h
@@ -46,8 +46,7 @@
         sp<MemoryHeapPmem>  mClientHeap;
     };
     
-    MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap,
-                uint32_t flags = IMemoryHeap::MAP_ONCE);
+    MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap, uint32_t flags = 0);
     ~MemoryHeapPmem();
 
     /* HeapInterface additions */
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 6c1d225..bc8c412 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -46,7 +46,6 @@
     virtual void binderDied(const wp<IBinder>& who);
 
     sp<IMemoryHeap> find_heap(const sp<IBinder>& binder); 
-    void pin_heap(const sp<IBinder>& binder); 
     void free_heap(const sp<IBinder>& binder); 
     sp<IMemoryHeap> get_heap(const sp<IBinder>& binder);
     void dump_heaps();
@@ -100,13 +99,9 @@
     static inline void dump_heaps() {
         gHeapCache->dump_heaps();       
     }
-    void inline pin_heap() const {
-        gHeapCache->pin_heap(const_cast<BpMemoryHeap*>(this)->asBinder());
-    }
 
     void assertMapped() const;
     void assertReallyMapped() const;
-    void pinHeap() const;
 
     mutable volatile int32_t mHeapId;
     mutable void*       mBase;
@@ -320,11 +315,6 @@
                         asBinder().get(), size, fd, strerror(errno));
                 close(fd);
             } else {
-                if (flags & MAP_ONCE) {
-                    //LOGD("pinning heap (binder=%p, size=%d, fd=%d",
-                    //        asBinder().get(), size, fd);
-                    pin_heap();
-                }
                 mSize = size;
                 mFlags = flags;
                 android_atomic_write(fd, &mHeapId);
@@ -421,19 +411,6 @@
     }
 }
 
-void HeapCache::pin_heap(const sp<IBinder>& binder) 
-{
-    Mutex::Autolock _l(mHeapCacheLock);
-    ssize_t i = mHeapCache.indexOfKey(binder);
-    if (i>=0) {
-        heap_info_t& info(mHeapCache.editValueAt(i));
-        android_atomic_inc(&info.count);
-        binder->linkToDeath(this);
-    } else {
-        LOGE("pin_heap binder=%p not found!!!", binder.get());
-    }    
-}
-
 void HeapCache::free_heap(const sp<IBinder>& binder)  {
     free_heap( wp<IBinder>(binder) );
 }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index a38be48..df07059 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -279,6 +279,12 @@
         mMode = AudioSystem.MODE_INVALID;
         setMode(AudioSystem.MODE_NORMAL, null);
         mMediaServerOk = true;
+
+        // Call setRingerModeInt() to apply correct mute
+        // state on streams affected by ringer mode.
+        mRingerModeMutedStreams = 0;
+        setRingerModeInt(getRingerMode(), false);
+
         AudioSystem.setErrorCallback(mAudioSystemCallback);
         loadSoundEffects();
 
@@ -1728,6 +1734,9 @@
     }
 
     private void makeA2dpDeviceUnavailableLater(String address) {
+        // prevent any activity on the A2DP audio output to avoid unwanted
+        // reconnection of the sink.
+        AudioSystem.setParameters("A2dpSuspended=true");
         // the device will be made unavailable later, so consider it disconnected right away
         mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
         // send the delayed message to make the device unavailable later
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index f845fec1..e80ece6 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -714,7 +714,12 @@
                     }
                 }
             }
-            if (isAudio) {
+            long rowId = entry.mRowId;
+            if (isAudio && rowId == 0) {
+                // Only set these for new entries. For existing entries, they
+                // may have been modified later, and we want to keep the current
+                // values so that custom ringtones still show up in the ringtone
+                // picker.
                 values.put(Audio.Media.IS_RINGTONE, ringtones);
                 values.put(Audio.Media.IS_NOTIFICATION, notifications);
                 values.put(Audio.Media.IS_ALARM, alarms);
@@ -764,7 +769,6 @@
             }
 
             Uri result = null;
-            long rowId = entry.mRowId;
             if (rowId == 0) {
                 // new file, insert it
                 result = mMediaProvider.insert(tableUri, values);
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 5ad0361..f904cdf 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -973,9 +973,12 @@
                     mEglDisplay, mEglConfig, holder);
 
             if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
-                Log.w("EglHelper", "createWindowSurface failed. mEglDisplay: " + mEglDisplay +
-                        " mEglConfig: " + mEglConfig + " holder: " + holder);
-                throwEglException("createWindowSurface");
+                int error = mEgl.eglGetError();
+                if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
+                    Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
+                    return null;
+                }
+                throwEglException("createWindowSurface", error);
             }
 
             /*
@@ -1019,9 +1022,16 @@
                  * get a new surface.
                  */
                 int error = mEgl.eglGetError();
-                if (error == EGL11.EGL_CONTEXT_LOST) {
+                switch(error) {
+                case EGL11.EGL_CONTEXT_LOST:
                     return false;
-                } else {
+                case EGL10.EGL_BAD_NATIVE_WINDOW:
+                    // The native window is bad, probably because the
+                    // window manager has closed it. Ignore this error,
+                    // on the expectation that the application will be closed soon.
+                    Log.e("EglHelper", "eglSwapBuffers returned EGL_BAD_NATIVE_WINDOW. tid=" + Thread.currentThread().getId());
+                    break;
+                default:
                     throwEglException("eglSwapBuffers", error);
                 }
             }
@@ -1292,6 +1302,10 @@
                             Log.w("GLThread", "egl createSurface");
                         }
                         gl = (GL10) mEglHelper.createSurface(getHolder());
+                        if (gl == null) {
+                            // Couldn't create a surface. Quit quietly.
+                            break;
+                        }
                         sGLThreadManager.checkGLDriver(gl);
                         createEglSurface = false;
                     }
diff --git a/services/java/com/android/server/NotificationPlayer.java b/services/java/com/android/server/NotificationPlayer.java
index 4c4da5a..acc4c85 100644
--- a/services/java/com/android/server/NotificationPlayer.java
+++ b/services/java/com/android/server/NotificationPlayer.java
@@ -95,6 +95,7 @@
                         audioManager.requestAudioFocus(null, mCmd.stream,
                                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
                     }
+                    player.setOnCompletionListener(NotificationPlayer.this);
                     player.start();
                     if (mPlayer != null) {
                         mPlayer.release();
@@ -125,7 +126,6 @@
                 t.start();
                 t.wait();
             }
-            mPlayer.setOnCompletionListener(this);
             //-----------------------------------
 
             long delay = SystemClock.uptimeMillis() - cmd.requestTime;
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 9838fd2..4d2d2f9 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -20,7 +20,6 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.Service;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -79,8 +78,6 @@
     private static final int TESTING_RESET_PERIOD_SEC = 60 * 10;
     private static final long TESTING_THRESHOLD = 1 * 1024 * 1024;
 
-    private static final int PERIOD_COUNT = 6;
-
     private int mPolicyPollPeriodSec;
     private long mPolicyThreshold;
     private int mPolicyThrottleValue;
@@ -106,7 +103,6 @@
     private String mIface;
 
     private static final int NOTIFICATION_WARNING   = 2;
-    private static final int NOTIFICATION_ALL       = 0xFFFFFFFF;
 
     private Notification mThrottlingNotification;
     private boolean mWarningNotificationSent = false;
@@ -177,32 +173,31 @@
                 "ThrottleService");
     }
 
+    private long ntpToWallTime(long ntpTime) {
+        long bestNow = getBestTime();
+        long localNow = System.currentTimeMillis();
+        return localNow + (ntpTime - bestNow);
+    }
+
     // TODO - fetch for the iface
     // return time in the local, system wall time, correcting for the use of ntp
+
     public synchronized long getResetTime(String iface) {
         enforceAccessPermission();
         long resetTime = 0;
         if (mRecorder != null) {
-            long bestEnd = mRecorder.getPeriodEnd();
-            long bestNow = getBestTime();
-            long localNow = System.currentTimeMillis();
-
-            resetTime = localNow + (bestEnd - bestNow);
+            resetTime = ntpToWallTime(mRecorder.getPeriodEnd());
         }
         return resetTime;
     }
 
     // TODO - fetch for the iface
-    // return time in the loca, system wall tiem, correcting for the use of ntp
+    // return time in the local, system wall time, correcting for the use of ntp
     public synchronized long getPeriodStartTime(String iface) {
         enforceAccessPermission();
         long startTime = 0;
         if (mRecorder != null) {
-            long bestStart = mRecorder.getPeriodStart();
-            long bestNow = getBestTime();
-            long localNow = System.currentTimeMillis();
-
-            startTime = localNow + (bestStart - bestNow);
+            startTime = ntpToWallTime(mRecorder.getPeriodStart());
         }
         return startTime;
     }
@@ -440,8 +435,8 @@
             Intent broadcast = new Intent(ThrottleManager.THROTTLE_POLL_ACTION);
             broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_READ, periodRx);
             broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_WRITE, periodTx);
-            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_START, ThrottleService.this.getPeriodStartTime(mIface));
-            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_END, ThrottleService.this.getResetTime(mIface));
+            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_START, getPeriodStartTime(mIface));
+            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_END, getResetTime(mIface));
             mContext.sendStickyBroadcast(broadcast);
 
             mAlarmManager.cancel(mPendingPollIntent);
@@ -625,6 +620,7 @@
 
                 if (mRecorder.setNextPeriod(start, end)) {
                     clearThrottleAndNotification();
+                    onPollAlarm();
                 }
 
                 mAlarmManager.cancel(mPendingResetIntent);
@@ -642,31 +638,40 @@
     private void checkForAuthoritativeTime() {
         if (mNtpActive || (mNtpServer == null)) return;
 
-        SntpClient client = new SntpClient();
-        if (client.requestTime(mNtpServer, 10000)) {
-            mNtpActive = true;
-            if (DBG) Slog.d(TAG, "found Authoritative time - reseting alarm");
-            mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
-        }
+        // will try to get the ntp time and switch to it if found.
+        // will also cache the time so we don't fetch it repeatedly.
+        getBestTime();
     }
 
-    private long getBestTime() {
-        SntpClient client = new SntpClient();
+    private static final int MAX_NTP_CACHE_AGE = 30 * 1000;
+    private static final int MAX_NTP_FETCH_WAIT = 10 * 1000;
+    private long cachedNtp;
+    private long cachedNtpTimestamp;
 
-        long time;
-        if ((mNtpServer != null) && client.requestTime(mNtpServer, 10000)) {
-            time = client.getNtpTime() ;
-            if (!mNtpActive) {
-                mNtpActive = true;
-                if (DBG) Slog.d(TAG, "found Authoritative time - reseting alarm");
-                mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
+    private long getBestTime() {
+        if (mNtpServer != null) {
+            if (mNtpActive) {
+                long ntpAge = SystemClock.elapsedRealtime() - cachedNtpTimestamp;
+                if (ntpAge < MAX_NTP_CACHE_AGE) {
+                    return cachedNtp + ntpAge;
+                }
             }
-            if (DBG) Slog.d(TAG, "using Authoritative time: " + time);
-        } else {
-            time = System.currentTimeMillis();
-            if (DBG) Slog.d(TAG, "using User time: " + time);
-            mNtpActive = false;
+            SntpClient client = new SntpClient();
+            if (client.requestTime(mNtpServer, MAX_NTP_FETCH_WAIT)) {
+                cachedNtp = client.getNtpTime();
+                cachedNtpTimestamp = SystemClock.elapsedRealtime();
+                if (!mNtpActive) {
+                    mNtpActive = true;
+                    if (DBG) Slog.d(TAG, "found Authoritative time - reseting alarm");
+                    mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
+                }
+                if (DBG) Slog.d(TAG, "using Authoritative time: " + cachedNtp);
+                return cachedNtp;
+            }
         }
+        long time = System.currentTimeMillis();
+        if (DBG) Slog.d(TAG, "using User time: " + time);
+        mNtpActive = false;
         return time;
     }
 
@@ -705,7 +710,6 @@
                 mPeriodStart = Calendar.getInstance();
                 mPeriodEnd = Calendar.getInstance();
 
-                zeroData(0);
                 retrieve();
             }
         }
@@ -915,6 +919,9 @@
         }
 
         private void retrieve() {
+            // clean out any old data first.  If we fail to read we don't want old stuff
+            zeroData(0);
+
             File f = getDataFile();
             byte[] buffer;
             FileInputStream s = null;
@@ -952,7 +959,7 @@
 
                 mPeriodCount = Integer.parseInt(parsed[parsedUsed++]);
                 if (parsed.length != 5 + (2 * mPeriodCount)) {
-                    Slog.e(TAG, "reading data file with bad length ("+parsed.length+" != "+(4 + (2*mPeriodCount))+") - ignoring");
+                    Slog.e(TAG, "reading data file with bad length ("+parsed.length+" != "+(5 + (2*mPeriodCount))+") - ignoring");
                     return;
                 }
 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 13690bc..7e095b5 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -123,6 +123,8 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
 
 public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
     static final String TAG = "ActivityManager";
@@ -927,7 +929,9 @@
      */
     final ProcessStats mProcessStats = new ProcessStats(
             MONITOR_THREAD_CPU_USAGE);
-    long mLastCpuTime = 0;
+    final AtomicLong mLastCpuTime = new AtomicLong(0);
+    final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
+
     long mLastWriteTime = 0;
 
     long mInitialStartTime = 0;
@@ -1430,7 +1434,7 @@
                         try {
                             synchronized(this) {
                                 final long now = SystemClock.uptimeMillis();
-                                long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
+                                long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
                                 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
                                 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
                                 //        + ", write delay=" + nextWriteDelay);
@@ -1438,12 +1442,12 @@
                                     nextCpuDelay = nextWriteDelay;
                                 }
                                 if (nextCpuDelay > 0) {
+                                    mProcessStatsMutexFree.set(true);
                                     this.wait(nextCpuDelay);
                                 }
                             }
                         } catch (InterruptedException e) {
                         }
-                        
                         updateCpuStatsNow();
                     } catch (Exception e) {
                         Slog.e(TAG, "Unexpected exception collecting process stats", e);
@@ -1470,22 +1474,26 @@
     }
 
     void updateCpuStats() {
-        synchronized (mProcessStatsThread) {
-            final long now = SystemClock.uptimeMillis();
-            if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
+        final long now = SystemClock.uptimeMillis();
+        if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
+            return;
+        }
+        if (mProcessStatsMutexFree.compareAndSet(true, false)) {
+            synchronized (mProcessStatsThread) {
                 mProcessStatsThread.notify();
             }
         }
     }
-    
+
     void updateCpuStatsNow() {
         synchronized (mProcessStatsThread) {
+            mProcessStatsMutexFree.set(false);
             final long now = SystemClock.uptimeMillis();
             boolean haveNewCpuStats = false;
 
             if (MONITOR_CPU_USAGE &&
-                    mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
-                mLastCpuTime = now;
+                    mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
+                mLastCpuTime.set(now);
                 haveNewCpuStats = true;
                 mProcessStats.update();
                 //Slog.i(TAG, mProcessStats.printCurrentState());
@@ -6133,12 +6141,10 @@
         if (!(pendingResult instanceof PendingIntentRecord)) {
             return null;
         }
-        synchronized(this) {
-            try {
-                PendingIntentRecord res = (PendingIntentRecord)pendingResult;
-                return res.key.packageName;
-            } catch (ClassCastException e) {
-            }
+        try {
+            PendingIntentRecord res = (PendingIntentRecord)pendingResult;
+            return res.key.packageName;
+        } catch (ClassCastException e) {
         }
         return null;
     }
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 4f84aab..978d821 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -735,6 +735,8 @@
                 mRunState = RUN_STATE_RUNNING;
                 noteRunState();
                 checkUseStaticIp();
+                /* Reset notification state on new connection */
+                resetNotificationTimer();
                 /*
                  * DHCP requests are blocking, so run them in a separate thread.
                  */