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;
}
}
}