Merge change 24754 into eclair

* changes:
  Handle secondary APN connect failures.
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index c211b47..c60045c 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -216,11 +216,9 @@
     } else
         vibrate_fd = -1;
 
-#if 0
     /* switch to non-root user and group */
     setgroups(sizeof(groups)/sizeof(groups[0]), groups);
     setuid(AID_SHELL);
-#endif
 
     /* make it safe to use both printf and STDOUT_FILENO */ 
     setvbuf(stdout, 0, _IONBF, 0);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 8c422a2..03346fe 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -185,7 +185,7 @@
 
         private final HandlerCaller mCaller;
 
-        private AccessibilityService mTarget;
+        private final AccessibilityService mTarget;
 
         public IEventListenerWrapper(AccessibilityService context) {
             mTarget = context;
@@ -211,9 +211,9 @@
             switch (message.what) {
                 case DO_ON_ACCESSIBILITY_EVENT :
                     AccessibilityEvent event = (AccessibilityEvent) message.obj;
-                    if (event != null){
-                      mTarget.onAccessibilityEvent(event);
-                      event.recycle();
+                    if (event != null) {
+                        mTarget.onAccessibilityEvent(event);
+                        event.recycle();
                     }
                     return;
                 case DO_ON_INTERRUPT :
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index d04abe5..9afeb74 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -21,11 +21,13 @@
 import android.content.Context;
 import android.content.IntentFilter;
 import android.content.BroadcastReceiver;
+import android.database.SQLException;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.Parcelable;
+import android.util.Log;
 
 import java.io.IOException;
 import java.util.concurrent.Callable;
@@ -364,7 +366,13 @@
         handler = (handler == null) ? mMainHandler : handler;
         handler.post(new Runnable() {
             public void run() {
-                listener.onAccountsUpdated(accountsCopy);
+                try {
+                    listener.onAccountsUpdated(accountsCopy);
+                } catch (SQLException e) {
+                    // Better luck next time.  If the problem was disk-full,
+                    // the STORAGE_OK intent will re-trigger the update.
+                    Log.e(TAG, "Can't update accounts", e);
+                }
             }
         });
     }
@@ -824,6 +832,8 @@
                 // Register a broadcast receiver to monitor account changes
                 IntentFilter intentFilter = new IntentFilter();
                 intentFilter.addAction(Constants.LOGIN_ACCOUNTS_CHANGED_ACTION);
+                // To recover from disk-full.
+                intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); 
                 mContext.registerReceiver(mAccountsChangedBroadcastReceiver, intentFilter);
             }
         }
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index a9cec50..b1861ac 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -250,7 +250,7 @@
      * @hide */
     public static final int BOND_SUCCESS = 0;
     /** A bond attempt failed because pins did not match, or remote device did
-     * not respond to pin request in time 
+     * not respond to pin request in time
      * @hide */
     public static final int UNBOND_REASON_AUTH_FAILED = 1;
     /** A bond attempt failed because the other side explicilty rejected
@@ -266,9 +266,15 @@
     /** A bond attempt failed because a discovery is in progress
      * @hide */
     public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
+    /** A bond attempt failed because of authentication timeout
+     * @hide */
+    public static final int UNBOND_REASON_AUTH_TIMEOUT = 6;
+    /** A bond attempt failed because of repeated attempts
+     * @hide */
+    public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7;
     /** An existing bond was explicitly revoked
      * @hide */
-    public static final int UNBOND_REASON_REMOVED = 6;
+    public static final int UNBOND_REASON_REMOVED = 8;
 
     /** The user will be prompted to enter a pin
      * @hide */
@@ -278,7 +284,13 @@
     public static final int PAIRING_VARIANT_PASSKEY = 1;
     /** The user will be prompted to confirm the passkey displayed on the screen
      * @hide */
-    public static final int PAIRING_VARIANT_CONFIRMATION = 2;
+    public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2;
+    /** The user will be prompted to accept or deny the incoming pairing request
+     * @hide */
+    public static final int PAIRING_VARIANT_CONSENT = 3;
+    /** The user will be prompted to enter the passkey displayed on remote device
+     * @hide */
+    public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;
 
     private static IBluetooth sService;  /* Guarenteed constant after first object constructed */
 
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 0bc8a9d..0d43b2a 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -24,7 +24,6 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Locale;
 
 /**
  * Provides access to an application's raw asset files; see {@link Resources}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 7d412a7..ba5c9ed 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -66,8 +66,6 @@
             = new SparseArray<ColorStateList>();
     private static boolean mPreloaded;
 
-    private final LongSparseArray<Drawable.ConstantState> mPreloadedDrawables;
-
     /*package*/ final TypedValue mTmpValue = new TypedValue();
 
     // These are protected by the mTmpValue lock.
@@ -158,11 +156,6 @@
         }
         updateConfiguration(config, metrics);
         assets.ensureStringBlocks();
-        if (mCompatibilityInfo.isScalingRequired()) {
-            mPreloadedDrawables = emptySparseArray();
-        } else {
-            mPreloadedDrawables = sPreloadedDrawables;
-        }
     }
 
     /**
@@ -1669,7 +1662,7 @@
             return dr;
         }
 
-        Drawable.ConstantState cs = mPreloadedDrawables.get(key);
+        Drawable.ConstantState cs = sPreloadedDrawables.get(key);
         if (cs != null) {
             dr = cs.newDrawable();
         } else {
@@ -1976,7 +1969,6 @@
         mMetrics.setToDefaults();
         updateConfiguration(null, null);
         mAssets.ensureStringBlocks();
-        mPreloadedDrawables = sPreloadedDrawables;
         mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
     }
 }
diff --git a/core/java/android/gesture/GestureOverlayView.java b/core/java/android/gesture/GestureOverlayView.java
index 5bfdcc4..30ecf5a 100755
--- a/core/java/android/gesture/GestureOverlayView.java
+++ b/core/java/android/gesture/GestureOverlayView.java
@@ -29,6 +29,7 @@
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.widget.FrameLayout;
 import android.os.SystemClock;
+import android.annotation.Widget;
 import com.android.internal.R;
 
 import java.util.ArrayList;
@@ -50,6 +51,7 @@
  * @attr ref android.R.styleable#GestureOverlayView_orientation
  * @attr ref android.R.styleable#GestureOverlayView_uncertainGestureColor
  */
+@Widget
 public class GestureOverlayView extends FrameLayout {
     public static final int GESTURE_STROKE_TYPE_SINGLE = 0;
     public static final int GESTURE_STROKE_TYPE_MULTIPLE = 1;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 97955ae..688f377 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2401,11 +2401,6 @@
             WIFI_NUM_ALLOWED_CHANNELS,
             WIFI_NUM_OPEN_NETWORKS_KEPT,
             BACKGROUND_DATA,
-            PREFERRED_NETWORK_MODE,
-            PREFERRED_TTY_MODE,
-            CDMA_CELL_BROADCAST_SMS,
-            PREFERRED_CDMA_SUBSCRIPTION,
-            ENHANCED_VOICE_PRIVACY_ENABLED
         };
 
         /**
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 4c24c50..1ed5c49 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -17,8 +17,8 @@
 package android.server;
 
 import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
@@ -53,6 +53,7 @@
 
     private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1;
     private static final int EVENT_RESTART_BLUETOOTH = 2;
+    private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 3;
 
     // The time (in millisecs) to delay the pairing attempt after the first
     // auto pairing attempt fails. We use an exponential delay with
@@ -67,9 +68,10 @@
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
+            String address = null;
             switch (msg.what) {
             case EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
-                String address = (String)msg.obj;
+                address = (String)msg.obj;
                 if (address != null) {
                     mBluetoothService.createBond(address);
                     return;
@@ -78,6 +80,12 @@
             case EVENT_RESTART_BLUETOOTH:
                 mBluetoothService.restart();
                 break;
+            case EVENT_PAIRING_CONSENT_DELAYED_ACCEPT:
+                address = (String)msg.obj;
+                if (address != null) {
+                    mBluetoothService.setPairingConfirmation(address, true);
+                }
+                break;
             }
         }
     };
@@ -166,6 +174,17 @@
         mContext.sendBroadcast(intent, BLUETOOTH_PERM);
     }
 
+    private void onDeviceDisconnectRequested(String deviceObjectPath) {
+        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
+        if (address == null) {
+            Log.e(TAG, "onDeviceDisconnectRequested: Address of the remote device in null");
+            return;
+        }
+        Intent intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
+        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
+        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
+    }
+
     private void onCreatePairedDeviceResult(String address, int result) {
         address = address.toUpperCase();
         if (result == BluetoothDevice.BOND_SUCCESS) {
@@ -228,6 +247,7 @@
                 addDevice(address, properties);
             }
         }
+        mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDING);
         return;
     }
 
@@ -379,7 +399,32 @@
         return address;
     }
 
-    private void onRequestConfirmation(String objectPath, int passkey, int nativeData) {
+    private void onRequestPairingConsent(String objectPath, int nativeData) {
+        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
+        if (address == null) return;
+
+        /* The link key will not be stored if the incoming request has MITM
+         * protection switched on. Unfortunately, some devices have MITM
+         * switched on even though their capabilities are NoInputNoOutput,
+         * so we may get this request many times. Also if we respond immediately,
+         * the other end is unable to handle it. Delay sending the message.
+         */
+        if (mBluetoothService.getBondState().getBondState(address) == BluetoothDevice.BOND_BONDED) {
+            Message message = mHandler.obtainMessage(EVENT_PAIRING_CONSENT_DELAYED_ACCEPT);
+            message.obj = address;
+            mHandler.sendMessageDelayed(message, 1500);
+            return;
+        }
+
+        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
+        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
+        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
+                        BluetoothDevice.PAIRING_VARIANT_CONSENT);
+        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
+        return;
+    }
+
+    private void onRequestPasskeyConfirmation(String objectPath, int passkey, int nativeData) {
         String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
         if (address == null) return;
 
@@ -387,7 +432,7 @@
         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
         intent.putExtra(BluetoothDevice.EXTRA_PASSKEY, passkey);
         intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                BluetoothDevice.PAIRING_VARIANT_CONFIRMATION);
+                BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION);
         mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
         return;
     }
@@ -436,6 +481,18 @@
         return;
     }
 
+    private void onDisplayPasskey(String objectPath, int passkey, int nativeData) {
+        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
+        if (address == null) return;
+
+        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
+        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
+        intent.putExtra(BluetoothDevice.EXTRA_PASSKEY, passkey);
+        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
+                        BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY);
+        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
+    }
+
     private boolean onAgentAuthorize(String objectPath, String deviceUuid) {
         String address = mBluetoothService.getAddressFromObjectPath(objectPath);
         if (address == null) {
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 53fb03c..6ce0f5f 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -1266,5 +1266,4 @@
     private native boolean setPairingConfirmationNative(String address, boolean confirm,
             int nativeData);
     private native boolean setDevicePropertyBooleanNative(String objectPath, String key, int value);
-
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2f17bbc..f63c2f1 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6038,16 +6038,23 @@
      * some form of this public, but should think about the API.
      */
     Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor) {
-        final int width = mRight - mLeft;
-        final int height = mBottom - mTop;
+        int width = mRight - mLeft;
+        int height = mBottom - mTop;
 
-        Bitmap bitmap = Bitmap.createBitmap(width, height, quality);
+        final AttachInfo attachInfo = mAttachInfo;
+        final float scale = attachInfo.mApplicationScale;
+        width = (int) ((width * scale) + 0.5f);
+        height = (int) ((height * scale) + 0.5f);
+        
+        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1,
+                height > 0 ? height : 1, quality);
         if (bitmap == null) {
             throw new OutOfMemoryError();
         }
 
+        bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
+        
         Canvas canvas;
-        final AttachInfo attachInfo = mAttachInfo;
         if (attachInfo != null) {
             canvas = attachInfo.mCanvas;
             if (canvas == null) {
@@ -6070,6 +6077,7 @@
 
         computeScroll();
         final int restoreCount = canvas.save();
+        canvas.scale(scale, scale);
         canvas.translate(-mScrollX, -mScrollY);
 
         // Temporarily remove the dirty mask
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a611d5a..e98fd13 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -732,7 +732,11 @@
             }
         } else if (digits != null) {
             mInput = DigitsKeyListener.getInstance(digits.toString());
-            mInputType = inputType;
+            // If no input type was specified, we will default to generic
+            // text, since we can't tell the IME about the set of digits
+            // that was selected.
+            mInputType = inputType != EditorInfo.TYPE_NULL
+                    ? inputType : EditorInfo.TYPE_CLASS_TEXT;
         } else if (inputType != EditorInfo.TYPE_NULL) {
             setInputType(inputType, true);
             singleLine = (inputType&(EditorInfo.TYPE_MASK_CLASS
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index fd5271e..50df0f7 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -1,4 +1,25 @@
+/*
+**
+** Copyright 2006, 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.
+*/
+
+#define LOG_TAG "9patch"
+#define LOG_NDEBUG 1
+
 #include <utils/ResourceTypes.h>
+#include <utils/Log.h>
 
 #include "SkCanvas.h"
 #include "SkRegion.h"
@@ -62,6 +83,9 @@
             
             if (destDensity == srcDensity || destDensity == 0
                     || srcDensity == 0) {
+                LOGV("Drawing unscaled 9-patch: (%g,%g)-(%g,%g)",
+                        SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
+                        SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom));
                 NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
             } else {
                 canvas->save();
@@ -74,6 +98,11 @@
                 bounds.fBottom = SkScalarDiv(bounds.fBottom-bounds.fTop, scale);
                 bounds.fLeft = bounds.fTop = 0;
     
+                LOGV("Drawing scaled 9-patch: (%g,%g)-(%g,%g) srcDensity=%d destDensity=%d",
+                        SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
+                        SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom),
+                        srcDensity, destDensity);
+                
                 NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
     
                 canvas->restore();
diff --git a/core/jni/android/graphics/NinePatchImpl.cpp b/core/jni/android/graphics/NinePatchImpl.cpp
index f82053c..ff24a87 100644
--- a/core/jni/android/graphics/NinePatchImpl.cpp
+++ b/core/jni/android/graphics/NinePatchImpl.cpp
@@ -16,8 +16,10 @@
 */
 
 #define LOG_TAG "NinePatch"
+#define LOG_NDEBUG 1
 
 #include <utils/ResourceTypes.h>
+#include <utils/Log.h>
 
 #include "SkBitmap.h"
 #include "SkCanvas.h"
@@ -25,7 +27,7 @@
 #include "SkPaint.h"
 #include "SkUnPreMultiply.h"
 
-#define USE_TRACEx
+#define USE_TRACE
 
 #ifdef USE_TRACE
     static bool gTrace;
@@ -106,6 +108,13 @@
     if (canvas && canvas->quickReject(bounds, SkCanvas::kBW_EdgeType)) {
         return;
     }
+
+    SkPaint defaultPaint;
+    if (NULL == paint) {
+        // matches default dither in NinePatchDrawable.java.
+        defaultPaint.setDither(true);
+        paint = &defaultPaint;
+    }
     
     // if our canvas is GL, draw this as a mesh, which will be faster than
     // in parts (which is faster for raster)
@@ -123,10 +132,10 @@
 
     SkASSERT(canvas || outRegion);
 
-#if 0
+#ifdef USE_TRACE
     if (canvas) {
         const SkMatrix& m = canvas->getTotalMatrix();
-        SkDebugf("ninepatch [%g %g %g] [%g %g %g]\n",
+        LOGV("ninepatch [%g %g %g] [%g %g %g]\n",
                  SkScalarToFloat(m[0]), SkScalarToFloat(m[1]), SkScalarToFloat(m[2]),
                  SkScalarToFloat(m[3]), SkScalarToFloat(m[4]), SkScalarToFloat(m[5]));
     }
@@ -134,10 +143,10 @@
 
 #ifdef USE_TRACE
     if (gTrace) {
-        SkDEBUGF(("======== ninepatch bounds [%g %g]\n", SkScalarToFloat(bounds.width()), SkScalarToFloat(bounds.height())));
-        SkDEBUGF(("======== ninepatch paint bm [%d,%d]\n", bitmap.width(), bitmap.height()));
-        SkDEBUGF(("======== ninepatch xDivs [%d,%d]\n", chunk.xDivs[0], chunk.xDivs[1]));
-        SkDEBUGF(("======== ninepatch yDivs [%d,%d]\n", chunk.yDivs[0], chunk.yDivs[1]));
+        LOGV("======== ninepatch bounds [%g %g]\n", SkScalarToFloat(bounds.width()), SkScalarToFloat(bounds.height()));
+        LOGV("======== ninepatch paint bm [%d,%d]\n", bitmap.width(), bitmap.height());
+        LOGV("======== ninepatch xDivs [%d,%d]\n", chunk.xDivs[0], chunk.xDivs[1]);
+        LOGV("======== ninepatch yDivs [%d,%d]\n", chunk.yDivs[0], chunk.yDivs[1]);
     }
 #endif
 
@@ -146,7 +155,7 @@
         (paint && paint->getXfermode() == NULL && paint->getAlpha() == 0))
     {
 #ifdef USE_TRACE
-        if (gTrace) SkDEBUGF(("======== abort ninepatch draw\n"));
+        if (gTrace) LOGV("======== abort ninepatch draw\n");
 #endif
         return;
     }
@@ -158,11 +167,6 @@
     if (bitmap.getPixels() == NULL)
         return;
 
-    SkPaint defaultPaint;
-    if (NULL == paint) {
-        paint = &defaultPaint;
-    }
-
     const bool hasXfer = paint->getXfermode() != NULL;
     SkRect      dst;
     SkIRect     src;
@@ -196,8 +200,8 @@
     }
     int numFixedYPixelsRemaining = bitmapHeight - numStretchyYPixelsRemaining;
 
-#if 0
-    SkDebugf("NinePatch [%d %d] bounds [%g %g %g %g] divs [%d %d]\n",
+#ifdef USE_TRACE
+    LOGV("NinePatch [%d %d] bounds [%g %g %g %g] divs [%d %d]\n",
              bitmap.width(), bitmap.height(),
              SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
              SkScalarToFloat(bounds.width()), SkScalarToFloat(bounds.height()),
@@ -300,13 +304,13 @@
                 goto nextDiv;
             }
             if (canvas) {
-#if 0
-                SkDebugf("-- src [%d %d %d %d] dst [%g %g %g %g]\n",
+#ifdef USE_TRACE
+                LOGV("-- src [%d %d %d %d] dst [%g %g %g %g]\n",
                          src.fLeft, src.fTop, src.width(), src.height(),
                          SkScalarToFloat(dst.fLeft), SkScalarToFloat(dst.fTop),
                          SkScalarToFloat(dst.width()), SkScalarToFloat(dst.height()));
                 if (2 == src.width() && SkIntToScalar(5) == dst.width()) {
-                    SkDebugf("--- skip patch\n");
+                    LOGV("--- skip patch\n");
                 }
 #endif
                 drawStretchyPatch(canvas, src, dst, bitmap, *paint, initColor,
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 8fe7487..e703ed8 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -45,13 +45,16 @@
 static jmethodID method_onDeviceDisappeared;
 static jmethodID method_onDeviceCreated;
 static jmethodID method_onDeviceRemoved;
+static jmethodID method_onDeviceDisconnectRequested;
 
 static jmethodID method_onCreatePairedDeviceResult;
 static jmethodID method_onGetDeviceServiceChannelResult;
 
 static jmethodID method_onRequestPinCode;
 static jmethodID method_onRequestPasskey;
-static jmethodID method_onRequestConfirmation;
+static jmethodID method_onRequestPasskeyConfirmation;
+static jmethodID method_onRequestPairingConsent;
+static jmethodID method_onDisplayPasskey;
 static jmethodID method_onAgentAuthorize;
 static jmethodID method_onAgentCancel;
 
@@ -84,6 +87,8 @@
                                                   "(Ljava/lang/String;)V");
     method_onDeviceCreated = env->GetMethodID(clazz, "onDeviceCreated", "(Ljava/lang/String;)V");
     method_onDeviceRemoved = env->GetMethodID(clazz, "onDeviceRemoved", "(Ljava/lang/String;)V");
+    method_onDeviceDisconnectRequested = env->GetMethodID(clazz, "onDeviceDisconnectRequested",
+                                                        "(Ljava/lang/String;)V");
 
     method_onCreatePairedDeviceResult = env->GetMethodID(clazz, "onCreatePairedDeviceResult",
                                                          "(Ljava/lang/String;I)V");
@@ -95,7 +100,11 @@
                                                "(Ljava/lang/String;I)V");
     method_onRequestPasskey = env->GetMethodID(clazz, "onRequestPasskey",
                                                "(Ljava/lang/String;I)V");
-    method_onRequestConfirmation = env->GetMethodID(clazz, "onRequestConfirmation",
+    method_onRequestPasskeyConfirmation = env->GetMethodID(clazz, "onRequestPasskeyConfirmation",
+                                               "(Ljava/lang/String;II)V");
+    method_onRequestPairingConsent = env->GetMethodID(clazz, "onRequestPairingConsent",
+                                               "(Ljava/lang/String;I)V");
+    method_onDisplayPasskey = env->GetMethodID(clazz, "onDisplayPasskey",
                                                "(Ljava/lang/String;II)V");
 
     field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I");
@@ -227,7 +236,7 @@
 
 
 const char * get_adapter_path(DBusConnection *conn) {
-    DBusMessage *msg, *reply = NULL;
+    DBusMessage *msg = NULL, *reply = NULL;
     DBusError err;
     const char *device_path = NULL;
     int attempt = 0;
@@ -815,6 +824,14 @@
                             str_array);
         } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
         goto success;
+    } else if (dbus_message_is_signal(msg,
+                                      "org.bluez.Device",
+                                      "DisconnectRequested")) {
+        const char *remote_device_path = dbus_message_get_path(msg);
+        env->CallVoidMethod(nat->me,
+                            method_onDeviceDisconnectRequested,
+                            env->NewStringUTF(remote_device_path));
+        goto success;
     }
 
     ret = a2dp_event_filter(msg, env);
@@ -845,9 +862,7 @@
 
     if (dbus_message_is_method_call(msg,
             "org.bluez.Agent", "Cancel")) {
-
         env->CallVoidMethod(nat->me, method_onAgentCancel);
-
         // reply
         DBusMessage *reply = dbus_message_new_method_return(msg);
         if (!reply) {
@@ -928,6 +943,24 @@
                                        int(msg));
         goto success;
     } else if (dbus_message_is_method_call(msg,
+            "org.bluez.Agent", "DisplayPasskey")) {
+        char *object_path;
+        uint32_t passkey;
+        if (!dbus_message_get_args(msg, NULL,
+                                   DBUS_TYPE_OBJECT_PATH, &object_path,
+                                   DBUS_TYPE_UINT32, &passkey,
+                                   DBUS_TYPE_INVALID)) {
+            LOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
+            goto failure;
+        }
+
+        dbus_message_ref(msg);  // increment refcount because we pass to java
+        env->CallVoidMethod(nat->me, method_onDisplayPasskey,
+                                       env->NewStringUTF(object_path),
+                                       passkey,
+                                       int(msg));
+        goto success;
+    } else if (dbus_message_is_method_call(msg,
             "org.bluez.Agent", "RequestConfirmation")) {
         char *object_path;
         uint32_t passkey;
@@ -940,12 +973,27 @@
         }
 
         dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestConfirmation,
+        env->CallVoidMethod(nat->me, method_onRequestPasskeyConfirmation,
                                        env->NewStringUTF(object_path),
                                        passkey,
                                        int(msg));
         goto success;
     } else if (dbus_message_is_method_call(msg,
+            "org.bluez.Agent", "RequestPairingConsent")) {
+        char *object_path;
+        if (!dbus_message_get_args(msg, NULL,
+                                   DBUS_TYPE_OBJECT_PATH, &object_path,
+                                   DBUS_TYPE_INVALID)) {
+            LOGE("%s: Invalid arguments for RequestPairingConsent() method", __FUNCTION__);
+            goto failure;
+        }
+
+        dbus_message_ref(msg);  // increment refcount because we pass to java
+        env->CallVoidMethod(nat->me, method_onRequestPairingConsent,
+                                       env->NewStringUTF(object_path),
+                                       int(msg));
+        goto success;
+    } else if (dbus_message_is_method_call(msg,
                   "org.bluez.Agent", "Release")) {
         // reply
         DBusMessage *reply = dbus_message_new_method_return(msg);
@@ -981,6 +1029,8 @@
 #define BOND_RESULT_AUTH_CANCELED 3
 #define BOND_RESULT_REMOTE_DEVICE_DOWN 4
 #define BOND_RESULT_DISCOVERY_IN_PROGRESS 5
+#define BOND_RESULT_AUTH_TIMEOUT 6
+#define BOND_RESULT_REPEATED_ATTEMPTS 7
 
 void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) {
     LOGV(__FUNCTION__);
@@ -1026,6 +1076,12 @@
                    !strcmp(err.message, "Discover in progress")) {
             LOGV("... error = %s (%s)\n", err.name, err.message);
             result = BOND_RESULT_DISCOVERY_IN_PROGRESS;
+        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.RepeatedAttempts")) {
+            LOGV("... error = %s (%s)\n", err.name, err.message);
+            result = BOND_RESULT_REPEATED_ATTEMPTS;
+        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationTimeout")) {
+            LOGV("... error = %s (%s)\n", err.name, err.message);
+            result = BOND_RESULT_AUTH_TIMEOUT;
         } else {
             LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
             result = BOND_RESULT_ERROR;
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index de921f1..0b71acb 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -455,8 +455,8 @@
         }
 
         if (!reply) {
-            LOGE("%s: Cannot create message reply to RequestConfirmation to "
-                 "D-Bus\n", __FUNCTION__);
+            LOGE("%s: Cannot create message reply to RequestPasskeyConfirmation or"
+                  "RequestPairingConsent to D-Bus\n", __FUNCTION__);
             dbus_message_unref(msg);
             return JNI_FALSE;
         }
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 1755d4f..30cef67 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -56,7 +56,8 @@
  */
 public class BitmapDrawable extends Drawable {
 
-    private static final int DEFAULT_PAINT_FLAGS = Paint.FILTER_BITMAP_FLAG;
+    private static final int DEFAULT_PAINT_FLAGS =
+            Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG;
     private BitmapState mBitmapState;
     private Bitmap mBitmap;
     private final Rect mDstRect = new Rect();   // Gravity.apply() sets this
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 6b50406..af1a289 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -19,12 +19,23 @@
 import android.graphics.*;
 
 public class DrawableContainer extends Drawable implements Drawable.Callback {
-    
+
+    /**
+     * To be proper, we should have a getter for dither (and alpha, etc.)
+     * so that proxy classes like this can save/restore their delegates'
+     * values, but we don't have getters. Since we do have setters
+     * (e.g. setDither), which this proxy forwards on, we have to have some
+     * default/initial setting.
+     *
+     * The initial setting for dither is now true, since it almost always seems
+     * to improve the quality at negligible cost.
+     */
+    private static final boolean DEFAULT_DITHER = true;
     private DrawableContainerState mDrawableContainerState;
     private Drawable mCurrDrawable;
     private int mAlpha = 0xFF;
     private ColorFilter mColorFilter;
-    private boolean mDither;
+    private boolean mDither = DEFAULT_DITHER;
 
     private int mCurIndex = -1;
     private boolean mMutated;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 1b1ea94..997efb8 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -21,6 +21,7 @@
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.util.TypedValue;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -36,6 +37,8 @@
  *
  */
 public class NinePatchDrawable extends Drawable {
+    // dithering helps a lot, and is pretty cheap, so default is true
+    private static final boolean DEFAULT_DITHER = true;
     private NinePatchState mNinePatchState;
     private NinePatch mNinePatch;
     private Rect mPadding;
@@ -101,7 +104,11 @@
         mNinePatch = state.mNinePatch;
         mPadding = state.mPadding;
         mTargetDensity = state.mTargetDensity;
-        if (state.mDither) setDither(state.mDither);
+        if (DEFAULT_DITHER != state.mDither) {
+            // avoid calling the setter unless we need to, since it does a
+            // lazy allocation of a paint
+            setDither(state.mDither);
+        }
         if (mNinePatch != null) {
             computeBitmapSize();
         }
@@ -164,6 +171,11 @@
 
     @Override
     public void draw(Canvas canvas) {
+        if (false) {
+            float[] pts = new float[2];
+            canvas.getMatrix().mapPoints(pts);
+            Log.v("9patch", "Drawing 9-patch @ " + pts[0] + "," + pts[1] + ": " + getBounds());
+        }
         mNinePatch.draw(canvas, getBounds(), mPaint);
     }
 
@@ -215,7 +227,8 @@
         }
 
         final boolean dither = a.getBoolean(
-                com.android.internal.R.styleable.NinePatchDrawable_dither, false);
+                com.android.internal.R.styleable.NinePatchDrawable_dither,
+                DEFAULT_DITHER);
         final BitmapFactory.Options options = new BitmapFactory.Options();
         if (dither) {
             options.inDither = false;
@@ -251,12 +264,10 @@
         a.recycle();
     }
 
-
     public Paint getPaint() {
         if (mPaint == null) {
             mPaint = new Paint();
-            // dithering helps a lot, and is pretty cheap, so default on
-            mPaint.setDither(true);
+            mPaint.setDither(DEFAULT_DITHER);
         }
         return mPaint;
     }
@@ -327,7 +338,7 @@
         int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
 
         NinePatchState(NinePatch ninePatch, Rect padding) {
-            this(ninePatch, padding, false);
+            this(ninePatch, padding, DEFAULT_DITHER);
         }
 
         NinePatchState(NinePatch ninePatch, Rect rect, boolean dither) {
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index a8274b1..59cb226 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -50,6 +50,17 @@
  * @attr ref android.R.styleable#DrawableStates_state_pressed
  */
 public class StateListDrawable extends DrawableContainer {
+    /**
+     * To be proper, we should have a getter for dither (and alpha, etc.)
+     * so that proxy classes like this can save/restore their delegates'
+     * values, but we don't have getters. Since we do have setters
+     * (e.g. setDither), which this proxy forwards on, we have to have some
+     * default/initial setting.
+     *
+     * The initial setting for dither is now true, since it almost always seems
+     * to improve the quality at negligible cost.
+     */
+    private static final boolean DEFAULT_DITHER = true;
     private final StateListState mStateListState;
     private boolean mMutated;
 
@@ -105,7 +116,8 @@
         mStateListState.setConstantSize(a.getBoolean(
                 com.android.internal.R.styleable.StateListDrawable_constantSize, false));
 
-        setDither(a.getBoolean(com.android.internal.R.styleable.StateListDrawable_dither, false));
+        setDither(a.getBoolean(com.android.internal.R.styleable.StateListDrawable_dither,
+                               DEFAULT_DITHER));
 
         a.recycle();
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 13db005..8cfd956 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -50,6 +50,7 @@
  * List of settings that are backed up are stored in the Settings.java file
  */
 public class SettingsBackupAgent extends BackupHelperAgent {
+    private static final boolean DEBUG = true;
 
     private static final String KEY_SYSTEM = "system";
     private static final String KEY_SECURE = "secure";
@@ -242,6 +243,13 @@
             pos += length;
             if (!TextUtils.isEmpty(settingName) && !TextUtils.isEmpty(settingValue)) {
                 //Log.i(TAG, "Restore " + settingName + " = " + settingValue);
+
+                // TODO: versioning rather than just an ad hoc blacklist to handle
+                // older varieties of backed-up data
+                if (invalidSavedSetting(contentUri, settingName, settingValue)) {
+                    continue;
+                }
+
                 if (mSettingsHelper.restoreValue(settingName, settingValue)) {
                     cv.clear();
                     cv.put(Settings.NameValueTable.NAME, settingName);
@@ -252,6 +260,22 @@
         }
     }
 
+    private boolean invalidSavedSetting(Uri contentUri, String settingName, String settingValue) {
+        // Even if these settings were stored, don't use them on restore
+        if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
+            if (settingName.equals(Settings.Secure.PREFERRED_NETWORK_MODE)
+                    || settingName.equals(Settings.Secure.PREFERRED_TTY_MODE)
+                    || settingName.equals(Settings.Secure.CDMA_CELL_BROADCAST_SMS)
+                    || settingName.equals(Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION)
+                    || settingName.equals(Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED)) {
+                if (DEBUG) Log.v(TAG, "Ignoring restore datum: " + settingName);
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     private String[] copyAndSort(String[] keys) {
         String[] sortedKeys = new String[keys.length];
         System.arraycopy(keys, 0, sortedKeys, 0, keys.length);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a744486..8914aceac 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -159,7 +159,8 @@
 
     /**
      * Returns the software version number for the device, for example,
-     * the IMEI/SV for GSM phones.
+     * the IMEI/SV for GSM phones. Return null if the software version is
+     * not available.
      *
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -168,13 +169,15 @@
         try {
             return getSubscriberInfo().getDeviceSvn();
         } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            return null;
         }
-        return null;
     }
 
     /**
-     * Returns the unique device ID, for example, the IMEI for GSM and the MEID for CDMA
-     * phones.
+     * Returns the unique device ID, for example, the IMEI for GSM and the MEID
+     * for CDMA phones. Return null if device ID is not available.
      *
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -183,12 +186,15 @@
         try {
             return getSubscriberInfo().getDeviceId();
         } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            return null;
         }
-        return null;
     }
 
     /**
      * Returns the current location of the device.
+     * Return null if current location is not available.
      *
      * <p>Requires Permission:
      * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
@@ -199,8 +205,10 @@
             Bundle bundle = getITelephony().getCellLocation();
             return CellLocation.newFromBundle(bundle);
         } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            return null;
         }
-        return null;
     }
 
     /**
@@ -216,6 +224,7 @@
         try {
             getITelephony().enableLocationUpdates();
         } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
         }
     }
 
@@ -232,6 +241,7 @@
         try {
             getITelephony().disableLocationUpdates();
         } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
         }
     }
 
@@ -247,9 +257,10 @@
        try {
            return getITelephony().getNeighboringCellInfo();
        } catch (RemoteException ex) {
+           return null;
+       } catch (NullPointerException ex) {
+           return null;
        }
-       return null;
-
     }
 
     /**
@@ -289,7 +300,11 @@
                 // This can happen when the ITelephony interface is not up yet.
                 return getPhoneTypeFromProperty();
             }
-        } catch(RemoteException ex){
+        } catch (RemoteException ex) {
+            // This shouldn't happen in the normal case, as a backup we
+            // read from the system property.
+            return getPhoneTypeFromProperty();
+        } catch (NullPointerException ex) {
             // This shouldn't happen in the normal case, as a backup we
             // read from the system property.
             return getPhoneTypeFromProperty();
@@ -418,9 +433,12 @@
                 // This can happen when the ITelephony interface is not up yet.
                 return NETWORK_TYPE_UNKNOWN;
             }
-        } catch(RemoteException ex){
+        } catch(RemoteException ex) {
             // This shouldn't happen in the normal case
             return NETWORK_TYPE_UNKNOWN;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return NETWORK_TYPE_UNKNOWN;
         }
     }
 
@@ -489,6 +507,9 @@
         } catch (RemoteException ex) {
             // Assume no ICC card if remote exception which shouldn't happen
             return false;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return false;
         }
     }
 
@@ -556,7 +577,8 @@
     }
 
     /**
-     * Returns the serial number of the SIM, if applicable.
+     * Returns the serial number of the SIM, if applicable. Return null if it is
+     * unavailable.
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -565,8 +587,11 @@
         try {
             return getSubscriberInfo().getIccSerialNumber();
         } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return null;
         }
-        return null;
     }
 
     //
@@ -577,6 +602,7 @@
 
     /**
      * Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
+     * Return null if it is unavailable.
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -585,13 +611,16 @@
         try {
             return getSubscriberInfo().getSubscriberId();
         } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return null;
         }
-        return null;
     }
 
     /**
      * Returns the phone number string for line 1, for example, the MSISDN
-     * for a GSM phone.
+     * for a GSM phone. Return null if it is unavailable.
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -600,12 +629,16 @@
         try {
             return getSubscriberInfo().getLine1Number();
         } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return null;
         }
-        return null;
     }
 
     /**
      * Returns the alphabetic identifier associated with the line 1 number.
+     * Return null if it is unavailable.
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -616,12 +649,15 @@
         try {
             return getSubscriberInfo().getLine1AlphaTag();
         } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return null;
         }
-        return null;
     }
 
     /**
-     * Returns the voice mail number.
+     * Returns the voice mail number. Return null if it is unavailable.
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -630,12 +666,15 @@
         try {
             return getSubscriberInfo().getVoiceMailNumber();
         } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return null;
         }
-        return null;
     }
 
     /**
-     * Returns the voice mail count.
+     * Returns the voice mail count. Return 0 if unavailable.
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -645,8 +684,11 @@
         try {
             return getITelephony().getVoiceMessageCount();
         } catch (RemoteException ex) {
+            return 0;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return 0;
         }
-        return 0;
     }
 
     /**
@@ -660,8 +702,11 @@
         try {
             return getSubscriberInfo().getVoiceMailAlphaTag();
         } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return null;
         }
-        return null;
     }
 
     private IPhoneSubInfo getSubscriberInfo() {
@@ -759,6 +804,8 @@
         } catch (RemoteException ex) {
             // the phone process is restarting.
             return DATA_DISCONNECTED;
+        } catch (NullPointerException ex) {
+            return DATA_DISCONNECTED;
         }
     }
 
@@ -802,6 +849,8 @@
             mRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);
         } catch (RemoteException ex) {
             // system process dead
+        } catch (NullPointerException ex) {
+            // system process dead
         }
     }
 
@@ -816,6 +865,8 @@
         } catch (RemoteException ex) {
             // the phone process is restarting.
             return -1;
+        } catch (NullPointerException ex) {
+            return -1;
         }
     }
 
@@ -832,6 +883,8 @@
         } catch (RemoteException ex) {
             // the phone process is restarting.
             return -1;
+        } catch (NullPointerException ex) {
+            return -1;
         }
     }
 
@@ -846,6 +899,8 @@
         } catch (RemoteException ex) {
             // the phone process is restarting.
             return null;
+        } catch (NullPointerException ex) {
+            return null;
         }
     }
 }