Merge "Fix NPE on devices that don't have NFC." into ics-mr1
diff --git a/Android.mk b/Android.mk
index 586eb4a..a748b7b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -412,6 +412,8 @@
resources/samples/BackupRestore "Backup and Restore" \
-samplecode $(sample_dir)/BluetoothChat \
resources/samples/BluetoothChat "Bluetooth Chat" \
+ -samplecode $(sample_dir)/BluetoothHDP \
+ resources/samples/BluetoothHDP "Bluetooth HDP Demo" \
-samplecode $(sample_dir)/BusinessCard \
resources/samples/BusinessCard "Business Card" \
-samplecode $(sample_dir)/ContactManager \
diff --git a/api/current.txt b/api/current.txt
index f33c6cb..cc50ff9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -83,6 +83,7 @@
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_PROFILE = "android.permission.READ_PROFILE";
field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
+ field public static final java.lang.String READ_SOCIAL_STREAM = "android.permission.READ_SOCIAL_STREAM";
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
field public static final java.lang.String REBOOT = "android.permission.REBOOT";
@@ -127,6 +128,7 @@
field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
field public static final java.lang.String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS";
field public static final java.lang.String WRITE_SMS = "android.permission.WRITE_SMS";
+ field public static final java.lang.String WRITE_SOCIAL_STREAM = "android.permission.WRITE_SOCIAL_STREAM";
field public static final java.lang.String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS";
}
@@ -14237,6 +14239,13 @@
method public static void texSubImage2D(int, int, int, int, android.graphics.Bitmap, int, int);
}
+ public abstract class ManagedEGLContext {
+ ctor public ManagedEGLContext(javax.microedition.khronos.egl.EGLContext);
+ method public javax.microedition.khronos.egl.EGLContext getContext();
+ method public abstract void onTerminate(javax.microedition.khronos.egl.EGLContext);
+ method public void terminate();
+ }
+
public class Matrix {
ctor public Matrix();
method public static void frustumM(float[], int, float, float, float, float, float, float);
@@ -18419,14 +18428,14 @@
ctor public RSSurfaceView(android.content.Context);
ctor public RSSurfaceView(android.content.Context, android.util.AttributeSet);
method public android.renderscript.RenderScriptGL createRenderScriptGL(android.renderscript.RenderScriptGL.SurfaceConfig);
- method public void destroyRenderScriptGL();
+ method public synchronized void destroyRenderScriptGL();
method public android.renderscript.RenderScriptGL getRenderScriptGL();
method public void pause();
method public void resume();
method public void setRenderScriptGL(android.renderscript.RenderScriptGL);
- method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
+ method public synchronized void surfaceChanged(android.view.SurfaceHolder, int, int, int);
method public void surfaceCreated(android.view.SurfaceHolder);
- method public void surfaceDestroyed(android.view.SurfaceHolder);
+ method public synchronized void surfaceDestroyed(android.view.SurfaceHolder);
}
public class RSTextureView extends android.view.TextureView implements android.view.TextureView.SurfaceTextureListener {
@@ -25145,7 +25154,7 @@
method public synchronized java.lang.String getFixedFontFamily();
method public synchronized boolean getJavaScriptCanOpenWindowsAutomatically();
method public synchronized boolean getJavaScriptEnabled();
- method public deprecated synchronized android.webkit.WebSettings.LayoutAlgorithm getLayoutAlgorithm();
+ method public synchronized android.webkit.WebSettings.LayoutAlgorithm getLayoutAlgorithm();
method public boolean getLightTouchEnabled();
method public boolean getLoadWithOverviewMode();
method public synchronized boolean getLoadsImagesAutomatically();
@@ -25192,7 +25201,7 @@
method public synchronized void setGeolocationEnabled(boolean);
method public synchronized void setJavaScriptCanOpenWindowsAutomatically(boolean);
method public synchronized void setJavaScriptEnabled(boolean);
- method public deprecated synchronized void setLayoutAlgorithm(android.webkit.WebSettings.LayoutAlgorithm);
+ method public synchronized void setLayoutAlgorithm(android.webkit.WebSettings.LayoutAlgorithm);
method public void setLightTouchEnabled(boolean);
method public void setLoadWithOverviewMode(boolean);
method public synchronized void setLoadsImagesAutomatically(boolean);
@@ -25227,12 +25236,12 @@
field public static final int LOAD_NO_CACHE = 2; // 0x2
}
- public static final deprecated class WebSettings.LayoutAlgorithm extends java.lang.Enum {
+ public static final class WebSettings.LayoutAlgorithm extends java.lang.Enum {
method public static android.webkit.WebSettings.LayoutAlgorithm valueOf(java.lang.String);
method public static final android.webkit.WebSettings.LayoutAlgorithm[] values();
enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm NARROW_COLUMNS;
enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm NORMAL;
- enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm SINGLE_COLUMN;
+ enum_constant public static final deprecated android.webkit.WebSettings.LayoutAlgorithm SINGLE_COLUMN;
}
public static final class WebSettings.PluginState extends java.lang.Enum {
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index aa62cd7..a2038c9 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -784,12 +784,12 @@
// machine. We don't handle AVCTP signals currently. We only send
// intents for AVDTP state changes. We need to handle both of them in
// some cases. For now, just don't move to incoming state in this case.
- mBluetoothService.notifyIncomingA2dpConnection(address, true);
+ mBluetoothService.notifyIncomingA2dpConnection(address, false);
} else {
Log.i(TAG, "" + authorized +
"Incoming A2DP / AVRCP connection from " + address);
mA2dp.allowIncomingConnect(device, authorized);
- mBluetoothService.notifyIncomingA2dpConnection(address, false);
+ mBluetoothService.notifyIncomingA2dpConnection(address, true);
}
} else if (BluetoothUuid.isInputDevice(uuid)) {
// We can have more than 1 input device connected.
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index e0167d8..8e39d6e 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -22,6 +22,9 @@
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.opengl.GLUtils;
+import android.opengl.ManagedEGLContext;
+import android.os.Handler;
+import android.os.Looper;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Log;
@@ -409,7 +412,8 @@
static final Object[] sEglLock = new Object[0];
int mWidth = -1, mHeight = -1;
- static final ThreadLocal<EGLContext> sEglContextStorage = new ThreadLocal<EGLContext>();
+ static final ThreadLocal<Gl20Renderer.MyEGLContext> sEglContextStorage
+ = new ThreadLocal<Gl20Renderer.MyEGLContext>();
EGLContext mEglContext;
Thread mEglThread;
@@ -561,12 +565,13 @@
}
}
- mEglContext = sEglContextStorage.get();
+ Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get();
+ mEglContext = managedContext != null ? managedContext.getContext() : null;
mEglThread = Thread.currentThread();
if (mEglContext == null) {
mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
- sEglContextStorage.set(mEglContext);
+ sEglContextStorage.set(new Gl20Renderer.MyEGLContext(mEglContext));
}
}
@@ -904,6 +909,51 @@
private static EGLSurface sPbuffer;
private static final Object[] sPbufferLock = new Object[0];
+ static class MyEGLContext extends ManagedEGLContext {
+ final Handler mHandler = new Handler();
+
+ public MyEGLContext(EGLContext context) {
+ super(context);
+ }
+
+ @Override
+ public void onTerminate(final EGLContext eglContext) {
+ // Make sure we do this on the correct thread.
+ if (mHandler.getLooper() != Looper.myLooper()) {
+ mHandler.post(new Runnable() {
+ @Override public void run() {
+ onTerminate(eglContext);
+ }
+ });
+ return;
+ }
+
+ synchronized (sEglLock) {
+ if (sEgl == null) return;
+
+ if (EGLImpl.getInitCount(sEglDisplay) == 1) {
+ usePbufferSurface(eglContext);
+ GLES20Canvas.terminateCaches();
+
+ sEgl.eglDestroyContext(sEglDisplay, eglContext);
+ sEglContextStorage.remove();
+
+ sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
+ sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+ sEgl.eglReleaseThread();
+ sEgl.eglTerminate(sEglDisplay);
+
+ sEgl = null;
+ sEglDisplay = null;
+ sEglConfig = null;
+ sPbuffer = null;
+ sEglContextStorage.set(null);
+ }
+ }
+ }
+ }
+
Gl20Renderer(boolean translucent) {
super(2, translucent);
}
@@ -1020,12 +1070,12 @@
static void trimMemory(int level) {
if (sEgl == null || sEglConfig == null) return;
- EGLContext eglContext = sEglContextStorage.get();
+ Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get();
// We do not have OpenGL objects
- if (eglContext == null) {
+ if (managedContext == null) {
return;
} else {
- usePbufferSurface(eglContext);
+ usePbufferSurface(managedContext.getContext());
}
switch (level) {
@@ -1052,33 +1102,5 @@
}
sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext);
}
-
- static void terminate() {
- synchronized (sEglLock) {
- if (sEgl == null) return;
-
- if (EGLImpl.getInitCount(sEglDisplay) == 1) {
- EGLContext eglContext = sEglContextStorage.get();
- if (eglContext == null) return;
-
- usePbufferSurface(eglContext);
- GLES20Canvas.terminateCaches();
-
- sEgl.eglDestroyContext(sEglDisplay, eglContext);
- sEglContextStorage.remove();
-
- sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
- sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
- sEgl.eglReleaseThread();
- sEgl.eglTerminate(sEglDisplay);
-
- sEgl = null;
- sEglDisplay = null;
- sEglConfig = null;
- sPbuffer = null;
- }
- }
- }
}
}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index d89bc36..660e3f4 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -21,6 +21,7 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
+import android.opengl.ManagedEGLContext;
import android.os.IBinder;
import android.util.AndroidRuntimeException;
import android.util.Log;
@@ -428,7 +429,7 @@
}
}
// Terminate the hardware renderer to free all resources
- HardwareRenderer.terminate();
+ ManagedEGLContext.doTerminate();
break;
}
// high end gfx devices fall through to next case
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index 0eb6e27..489587e 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -201,7 +201,7 @@
private static final int TASK_CLOSE = 3;
private final Queue<SpellCheckerParams> mPendingTasks =
new LinkedList<SpellCheckerParams>();
- private final Handler mHandler;
+ private Handler mHandler;
private boolean mOpened;
private ISpellCheckerSession mISpellCheckerSession;
@@ -334,6 +334,7 @@
try {
mISpellCheckerSession.onClose();
mISpellCheckerSession = null;
+ mHandler = null;
} catch (RemoteException e) {
Log.e(TAG, "Failed to close " + e);
}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index f240a2e..f947f95 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -42,12 +42,14 @@
* SINGLE_COLUMN moves all content into one column that is the width of the
* view.
* NARROW_COLUMNS makes all columns no wider than the screen if possible.
- * @deprecated This enum is now obsolete.
*/
// XXX: These must match LayoutAlgorithm in Settings.h in WebCore.
- @Deprecated
public enum LayoutAlgorithm {
NORMAL,
+ /**
+ * @deprecated This algorithm is now obsolete.
+ */
+ @Deprecated
SINGLE_COLUMN,
NARROW_COLUMNS
}
@@ -799,7 +801,7 @@
public void setDefaultZoom(ZoomDensity zoom) {
if (mDefaultZoom != zoom) {
mDefaultZoom = zoom;
- mWebView.updateDefaultZoomDensity(zoom.value);
+ mWebView.adjustDefaultZoomDensity(zoom.value);
}
}
@@ -936,9 +938,7 @@
* WebView.
* @param l A LayoutAlgorithm enum specifying the algorithm to use.
* @see WebSettings.LayoutAlgorithm
- * @deprecated This method is now obsolete.
*/
- @Deprecated
public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
// XXX: This will only be affective if libwebcore was built with
// ANDROID_LAYOUT defined.
@@ -953,9 +953,7 @@
* @return LayoutAlgorithm enum value describing the layout algorithm
* being used.
* @see WebSettings.LayoutAlgorithm
- * @deprecated This method is now obsolete.
*/
- @Deprecated
public synchronized LayoutAlgorithm getLayoutAlgorithm() {
return mLayoutAlgorithm;
}
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 8aafc3d..f18a396 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -17,8 +17,10 @@
package android.webkit;
import android.content.Context;
+import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
@@ -49,6 +51,7 @@
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
+import android.widget.AbsoluteLayout;
import android.widget.AbsoluteLayout.LayoutParams;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
@@ -71,6 +74,9 @@
static final String LOGTAG = "webtextview";
+ private Paint mRingPaint;
+ private int mRingInset;
+
private WebView mWebView;
private boolean mSingle;
private int mWidthSpec;
@@ -201,7 +207,13 @@
}
}
};
+ float ringWidth = 4f * context.getResources().getDisplayMetrics().density;
mReceiver = new MyResultReceiver(mHandler);
+ mRingPaint = new Paint();
+ mRingPaint.setColor(0x6633b5e5);
+ mRingPaint.setStrokeWidth(ringWidth);
+ mRingPaint.setStyle(Style.FILL);
+ mRingInset = (int) ringWidth;
}
public void setAutoFillable(int queryId) {
@@ -211,6 +223,40 @@
}
@Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (isFocused()) {
+ final int ib = getHeight() - mRingInset;
+ canvas.drawRect(0, 0, getWidth(), mRingInset, mRingPaint);
+ canvas.drawRect(0, ib, getWidth(), getHeight(), mRingPaint);
+ canvas.drawRect(0, mRingInset, mRingInset, ib, mRingPaint);
+ canvas.drawRect(getWidth() - mRingInset, mRingInset, getWidth(), ib, mRingPaint);
+ }
+ }
+
+ private void growOrShrink(boolean grow) {
+ AbsoluteLayout.LayoutParams lp = (AbsoluteLayout.LayoutParams) getLayoutParams();
+ if (grow) {
+ Log.i("webtextview", "grow");
+ lp.x -= mRingInset;
+ lp.y -= mRingInset;
+ lp.width += 2 * mRingInset;
+ lp.height += 2 * mRingInset;
+ setPadding(getPaddingLeft() + mRingInset, getPaddingTop() + mRingInset,
+ getPaddingRight() + mRingInset, getPaddingBottom() + mRingInset);
+ } else {
+ Log.i("webtextview", "shrink");
+ lp.x += mRingInset;
+ lp.y += mRingInset;
+ lp.width -= 2 * mRingInset;
+ lp.height -= 2 * mRingInset;
+ setPadding(getPaddingLeft() - mRingInset, getPaddingTop() - mRingInset,
+ getPaddingRight() - mRingInset, getPaddingBottom() - mRingInset);
+ }
+ setLayoutParams(lp);
+ }
+
+ @Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.isSystem()) {
return super.dispatchKeyEvent(event);
@@ -511,6 +557,7 @@
} else if (!mInsideRemove) {
mWebView.setActive(false);
}
+ growOrShrink(focused);
mFromFocusChange = false;
}
@@ -567,7 +614,6 @@
mPreChange.substring(0, mMaxLength).equals(postChange))) {
return;
}
- mPreChange = postChange;
if (0 == count) {
if (before > 0) {
// For this and all changes to the text, update our cache
@@ -605,9 +651,9 @@
// Prefer sending javascript events, so when adding one character,
// don't replace the unchanged text.
if (count > 1 && before == count - 1) {
- String replaceButOne = s.subSequence(start,
+ String replaceButOne = mPreChange.subSequence(start,
start + before).toString();
- String replacedString = getText().subSequence(start,
+ String replacedString = s.subSequence(start,
start + before).toString();
if (replaceButOne.equals(replacedString)) {
// we're just adding one character
@@ -616,6 +662,7 @@
count = 1;
}
}
+ mPreChange = postChange;
// Find the last character being replaced. If it can be represented by
// events, we will pass them to native so we can see javascript events.
// Otherwise, replace the text being changed in the textfield.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index ec2f55b..35fd945 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -119,6 +119,11 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import static javax.microedition.khronos.egl.EGL10.*;
+
/**
* <p>A View that displays web pages. This class is the basis upon which you
* can roll your own web browser or simply display some online content within your Activity.
@@ -909,6 +914,9 @@
private Rect mScrollingLayerBounds = new Rect();
private boolean mSentAutoScrollMessage = false;
+ // Temporary hack to work around the context removal upon memory pressure
+ private static boolean mIncrementEGLContextHack = false;
+
// used for serializing asynchronously handled touch events.
private final TouchEventQueue mTouchEventQueue = new TouchEventQueue();
@@ -1341,9 +1349,13 @@
}
}
- /* package */void updateDefaultZoomDensity(int zoomDensity) {
+ /* package */ void adjustDefaultZoomDensity(int zoomDensity) {
final float density = mContext.getResources().getDisplayMetrics().density
* 100 / zoomDensity;
+ updateDefaultZoomDensity(density);
+ }
+
+ /* package */ void updateDefaultZoomDensity(float density) {
mNavSlop = (int) (16 * density);
mZoomManager.updateDefaultZoomDensity(density);
}
@@ -2469,7 +2481,9 @@
* Set the initial scale for the WebView. 0 means default. If
* {@link WebSettings#getUseWideViewPort()} is true, it zooms out all the
* way. Otherwise it starts with 100%. If initial scale is greater than 0,
- * WebView starts will this value as initial scale.
+ * WebView starts with this value as initial scale.
+ * Please note that unlike the scale properties in the viewport meta tag,
+ * this method doesn't take the screen density into account.
*
* @param scaleInPercent The initial scale in percent.
*/
@@ -4219,6 +4233,13 @@
}
if (canvas.isHardwareAccelerated()) {
+ if (mIncrementEGLContextHack == false) {
+ mIncrementEGLContextHack = true;
+ EGL10 egl = (EGL10) EGLContext.getEGL();
+ EGLDisplay eglDisplay = egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ int[] version = new int[2];
+ egl.eglInitialize(eglDisplay, version);
+ }
mZoomManager.setHardwareAccelerated();
}
@@ -5658,13 +5679,13 @@
if (hasFocus()) {
// If our window regained focus, and we have focus, then begin
// drawing the cursor ring
- mDrawCursorRing = true;
+ mDrawCursorRing = !inEditingMode();
setFocusControllerActive(true);
} else {
+ mDrawCursorRing = false;
if (!inEditingMode()) {
// If our window gained focus, but we do not have it, do not
// draw the cursor ring.
- mDrawCursorRing = false;
setFocusControllerActive(false);
}
// We do not call recordButtons here because we assume
@@ -5739,7 +5760,7 @@
// When we regain focus, if we have window focus, resume drawing
// the cursor ring
if (hasWindowFocus()) {
- mDrawCursorRing = true;
+ mDrawCursorRing = !inEditingMode();
setFocusControllerActive(true);
//} else {
// The WebView has gained focus while we do not have
@@ -5749,8 +5770,8 @@
} else {
// When we lost focus, unless focus went to the TextView (which is
// true if we are in editing mode), stop drawing the cursor ring.
+ mDrawCursorRing = false;
if (!inEditingMode()) {
- mDrawCursorRing = false;
setFocusControllerActive(false);
}
mKeysPressed.clear();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index cd61481..a97f4dd 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2336,6 +2336,9 @@
adjust = (float) mContext.getResources().getDisplayMetrics().densityDpi
/ mViewportDensityDpi;
}
+ if (adjust != mWebView.getDefaultZoomScale()) {
+ mWebView.updateDefaultZoomDensity(adjust);
+ }
int defaultScale = (int) (adjust * 100);
if (mViewportInitialScale > 0) {
@@ -2546,7 +2549,7 @@
// called by JNI
private void restoreScale(float scale, float textWrapScale) {
if (mBrowserFrame.firstLayoutDone() == false) {
- mIsRestored = scale > 0;
+ mIsRestored = true;
mRestoredScale = scale;
if (mSettings.getUseWideViewPort()) {
mRestoredTextWrapScale = textWrapScale;
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index e1392ae..695c154 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -42,7 +42,7 @@
// log tag
protected static final String LOGTAG = "webviewdatabase";
- private static final int DATABASE_VERSION = 10;
+ private static final int DATABASE_VERSION = 11;
// 2 -> 3 Modified Cache table to allow cache of redirects
// 3 -> 4 Added Oma-Downloads table
// 4 -> 5 Modified Cache table to support persistent contentLength
@@ -52,6 +52,9 @@
// 7 -> 8 Move cache to its own db
// 8 -> 9 Store both scheme and host when storing passwords
// 9 -> 10 Update httpauth table UNIQUE
+ // 10 -> 11 Drop cookies and cache now managed by the chromium stack,
+ // and update the form data table to use the new format
+ // implemented for b/5265606.
private static final int CACHE_DATABASE_VERSION = 4;
// 1 -> 2 Add expires String
// 2 -> 3 Add content-disposition
@@ -204,7 +207,9 @@
}
initDatabase(context);
- if (!JniUtil.useChromiumHttpStack()) {
+ if (JniUtil.useChromiumHttpStack()) {
+ context.deleteDatabase(CACHE_DATABASE_FILE);
+ } else {
initCacheDatabase(context);
}
@@ -327,15 +332,59 @@
}
private static void upgradeDatabase() {
+ upgradeDatabaseToV10();
+ upgradeDatabaseFromV10ToV11();
+ // Add future database upgrade functions here, one version at a
+ // time.
+ mDatabase.setVersion(DATABASE_VERSION);
+ }
+
+ private static void upgradeDatabaseFromV10ToV11() {
int oldVersion = mDatabase.getVersion();
+
+ if (oldVersion >= 11) {
+ // Nothing to do.
+ return;
+ }
+
+ if (JniUtil.useChromiumHttpStack()) {
+ // Clear out old java stack cookies - this data is now stored in
+ // a separate database managed by the Chrome stack.
+ mDatabase.execSQL("DROP TABLE IF EXISTS " + mTableNames[TABLE_COOKIES_ID]);
+
+ // Likewise for the old cache table.
+ mDatabase.execSQL("DROP TABLE IF EXISTS cache");
+ }
+
+ // Update form autocomplete URLs to match new ICS formatting.
+ Cursor c = mDatabase.query(mTableNames[TABLE_FORMURL_ID], null, null,
+ null, null, null, null);
+ while (c.moveToNext()) {
+ String urlId = Long.toString(c.getLong(c.getColumnIndex(ID_COL)));
+ String url = c.getString(c.getColumnIndex(FORMURL_URL_COL));
+ ContentValues cv = new ContentValues(1);
+ cv.put(FORMURL_URL_COL, WebTextView.urlForAutoCompleteData(url));
+ mDatabase.update(mTableNames[TABLE_FORMURL_ID], cv, ID_COL + "=?",
+ new String[] { urlId });
+ }
+ c.close();
+ }
+
+ private static void upgradeDatabaseToV10() {
+ int oldVersion = mDatabase.getVersion();
+
+ if (oldVersion >= 10) {
+ // Nothing to do.
+ return;
+ }
+
if (oldVersion != 0) {
Log.i(LOGTAG, "Upgrading database from version "
+ oldVersion + " to "
+ DATABASE_VERSION + ", which will destroy old data");
}
- boolean justPasswords = 8 == oldVersion && 9 == DATABASE_VERSION;
- boolean justAuth = 9 == oldVersion && 10 == DATABASE_VERSION;
- if (justAuth) {
+
+ if (9 == oldVersion) {
mDatabase.execSQL("DROP TABLE IF EXISTS "
+ mTableNames[TABLE_HTTPAUTH_ID]);
mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
@@ -348,55 +397,49 @@
return;
}
- if (!justPasswords) {
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_COOKIES_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS cache");
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_FORMURL_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_FORMDATA_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_HTTPAUTH_ID]);
- }
+ mDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_COOKIES_ID]);
+ mDatabase.execSQL("DROP TABLE IF EXISTS cache");
+ mDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_FORMURL_ID]);
+ mDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_FORMDATA_ID]);
+ mDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_HTTPAUTH_ID]);
mDatabase.execSQL("DROP TABLE IF EXISTS "
+ mTableNames[TABLE_PASSWORD_ID]);
- mDatabase.setVersion(DATABASE_VERSION);
+ // cookies
+ mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_COOKIES_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + COOKIES_NAME_COL + " TEXT, " + COOKIES_VALUE_COL
+ + " TEXT, " + COOKIES_DOMAIN_COL + " TEXT, "
+ + COOKIES_PATH_COL + " TEXT, " + COOKIES_EXPIRES_COL
+ + " INTEGER, " + COOKIES_SECURE_COL + " INTEGER" + ");");
+ mDatabase.execSQL("CREATE INDEX cookiesIndex ON "
+ + mTableNames[TABLE_COOKIES_ID] + " (path)");
- if (!justPasswords) {
- // cookies
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_COOKIES_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + COOKIES_NAME_COL + " TEXT, " + COOKIES_VALUE_COL
- + " TEXT, " + COOKIES_DOMAIN_COL + " TEXT, "
- + COOKIES_PATH_COL + " TEXT, " + COOKIES_EXPIRES_COL
- + " INTEGER, " + COOKIES_SECURE_COL + " INTEGER" + ");");
- mDatabase.execSQL("CREATE INDEX cookiesIndex ON "
- + mTableNames[TABLE_COOKIES_ID] + " (path)");
+ // formurl
+ mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
+ + " TEXT" + ");");
- // formurl
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
- + " TEXT" + ");");
+ // formdata
+ mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMDATA_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + FORMDATA_URLID_COL + " INTEGER, " + FORMDATA_NAME_COL
+ + " TEXT, " + FORMDATA_VALUE_COL + " TEXT," + " UNIQUE ("
+ + FORMDATA_URLID_COL + ", " + FORMDATA_NAME_COL + ", "
+ + FORMDATA_VALUE_COL + ") ON CONFLICT IGNORE);");
- // formdata
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMDATA_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + FORMDATA_URLID_COL + " INTEGER, " + FORMDATA_NAME_COL
- + " TEXT, " + FORMDATA_VALUE_COL + " TEXT," + " UNIQUE ("
- + FORMDATA_URLID_COL + ", " + FORMDATA_NAME_COL + ", "
- + FORMDATA_VALUE_COL + ") ON CONFLICT IGNORE);");
-
- // httpauth
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
- + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
- + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
- + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
- + ") ON CONFLICT REPLACE);");
- }
+ // httpauth
+ mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
+ + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
+ + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
+ + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
+ + ") ON CONFLICT REPLACE);");
// passwords
mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_PASSWORD_ID]
+ " (" + ID_COL + " INTEGER PRIMARY KEY, "
@@ -411,7 +454,7 @@
if (oldVersion != 0) {
Log.i(LOGTAG, "Upgrading cache database from version "
+ oldVersion + " to "
- + DATABASE_VERSION + ", which will destroy all old data");
+ + CACHE_DATABASE_VERSION + ", which will destroy all old data");
}
mCacheDatabase.execSQL("DROP TABLE IF EXISTS cache");
mCacheDatabase.setVersion(CACHE_DATABASE_VERSION);
@@ -1150,7 +1193,7 @@
cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
ID_PROJECTION, urlSelection, new String[] { url }, null,
null, null);
- if (cursor.moveToFirst()) {
+ while (cursor.moveToNext()) {
long urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
Cursor dataCursor = null;
try {
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index f599dba..84d00c9 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -349,7 +349,7 @@
}
public final void setInitialScaleInPercent(int scaleInPercent) {
- mInitialScale = scaleInPercent * mDisplayDensity * 0.01f;
+ mInitialScale = scaleInPercent * 0.01f;
}
public final float computeScaleWithLimits(float scale) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 230df39..97658a1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -263,8 +263,7 @@
android:label="@string/permlab_writeProfile"
android:description="@string/permdesc_writeProfile" />
- <!-- Allows an application to read from the user's social stream.
- @hide -->
+ <!-- Allows an application to read from the user's social stream. -->
<permission android:name="android.permission.READ_SOCIAL_STREAM"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:protectionLevel="dangerous"
@@ -272,8 +271,7 @@
android:description="@string/permdesc_readSocialStream" />
<!-- Allows an application to write (but not read) the user's
- social stream data.
- @hide -->
+ social stream data. -->
<permission android:name="android.permission.WRITE_SOCIAL_STREAM"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:protectionLevel="dangerous"
diff --git a/core/res/res/layout/media_controller.xml b/core/res/res/layout/media_controller.xml
index 582101a..313806cd 100644
--- a/core/res/res/layout/media_controller.xml
+++ b/core/res/res/layout/media_controller.xml
@@ -17,13 +17,9 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="#CC666666"
+ android:background="#CC000000"
android:orientation="vertical">
- <ImageView android:layout_width="match_parent"
- android:layout_height="1px"
- android:background="@android:drawable/divider_horizontal_dark" />
-
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 767cafe..25f7d25 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -741,4 +741,7 @@
<string name="config_wimaxServiceClassname"></string>
<!-- Name of the wimax state tracker clas -->
<string name="config_wimaxStateTrackerClassname"></string>
+
+ <!-- Name of screensaver components to look for if none has been chosen by the user -->
+ <string name="config_defaultDreamComponent">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
</resources>
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index d7dd4d6..27d863d 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -271,7 +271,8 @@
mRequestBufferCalled(false),
mTransform(0),
mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0) {
+ mTimestamp(0),
+ mFrameNumber(0) {
mCrop.makeInvalid();
}
@@ -340,6 +341,10 @@
// mTimestamp is the current timestamp for this buffer slot. This gets
// to set by queueBuffer each time this slot is queued.
int64_t mTimestamp;
+
+ // mFrameNumber is the number of the queued frame for this slot.
+ uint64_t mFrameNumber;
+
};
// mSlots is the array of buffer slots that must be mirrored on the client
@@ -476,6 +481,12 @@
// around a GL driver limitation on the number of FBO attachments, which the
// browser's tile cache exceeds.
const GLenum mTexTarget;
+
+ // mFrameCounter is the free running counter, incremented for every buffer queued
+ // with the surface Texture.
+ uint64_t mFrameCounter;
+
+
};
// ----------------------------------------------------------------------------
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 9767568..ed319f5 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -32,10 +32,6 @@
LOCAL_MODULE:= libgui
-ifeq ($(TARGET_BOARD_PLATFORM), tegra)
- LOCAL_CFLAGS += -DALLOW_DEQUEUE_CURRENT_BUFFER
-endif
-
include $(BUILD_SHARED_LIBRARY)
ifeq (,$(ONE_SHOT_MAKEFILE))
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 374f3c5..3c0d475 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -36,12 +36,8 @@
#include <utils/Log.h>
#include <utils/String8.h>
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER true
-#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
-#else
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER false
-#endif
+
+#define ALLOW_DEQUEUE_CURRENT_BUFFER false
// Macros for including the SurfaceTexture name in log messages
#define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
@@ -116,7 +112,8 @@
mAllowSynchronousMode(allowSynchronousMode),
mConnectedApi(NO_CONNECTED_API),
mAbandoned(false),
- mTexTarget(texTarget) {
+ mTexTarget(texTarget),
+ mFrameCounter(0) {
// Choose a name using the PID and a process-unique ID.
mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
@@ -264,7 +261,8 @@
status_t returnFlags(OK);
- int found, foundSync;
+ int found = -1;
+ int foundSync = -1;
int dequeuedCount = 0;
bool tryAgain = true;
while (tryAgain) {
@@ -327,7 +325,7 @@
LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
"dequeueBuffer: buffer %d is both FREE and current!", i);
- if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) {
+ if (ALLOW_DEQUEUE_CURRENT_BUFFER) {
if (state == BufferSlot::FREE || i == mCurrentTexture) {
foundSync = i;
if (i != mCurrentTexture) {
@@ -337,9 +335,14 @@
}
} else {
if (state == BufferSlot::FREE) {
- foundSync = i;
- found = i;
- break;
+ /** For Asynchronous mode, we need to return the oldest of free buffers
+ * There is only one instance when the Framecounter overflows, this logic
+ * might return the earlier buffer to client. Which is a negligible impact
+ **/
+ if (found < 0 || mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
+ foundSync = i;
+ found = i;
+ }
}
}
}
@@ -531,6 +534,9 @@
mSlots[buf].mTransform = mNextTransform;
mSlots[buf].mScalingMode = mNextScalingMode;
mSlots[buf].mTimestamp = timestamp;
+ mFrameCounter++;
+ mSlots[buf].mFrameNumber = mFrameCounter;
+
mDequeueCondition.signal();
*outWidth = mDefaultWidth;
@@ -564,6 +570,7 @@
return;
}
mSlots[buf].mBufferState = BufferSlot::FREE;
+ mSlots[buf].mFrameNumber = 0;
mDequeueCondition.signal();
}
@@ -897,6 +904,7 @@
void SurfaceTexture::freeBufferLocked(int i) {
mSlots[i].mGraphicBuffer = 0;
mSlots[i].mBufferState = BufferSlot::FREE;
+ mSlots[i].mFrameNumber = 0;
if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 7d9d7ed..f6d054d 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -224,17 +224,18 @@
mClient.disconnect();
}
-void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
+void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) {
mQueue.cancelEvent(mVideoEvent->eventID());
mVideoEventPending = false;
- mQueue.cancelEvent(mStreamDoneEvent->eventID());
- mStreamDoneEventPending = false;
- mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
- mAudioStatusEventPending = false;
mQueue.cancelEvent(mVideoLagEvent->eventID());
mVideoLagEventPending = false;
- if (!keepBufferingGoing) {
+ if (!keepNotifications) {
+ mQueue.cancelEvent(mStreamDoneEvent->eventID());
+ mStreamDoneEventPending = false;
+ mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
+ mAudioStatusEventPending = false;
+
mQueue.cancelEvent(mBufferingEvent->eventID());
mBufferingEventPending = false;
}
@@ -1095,7 +1096,7 @@
return OK;
}
- cancelPlayerEvents(true /* keepBufferingGoing */);
+ cancelPlayerEvents(true /* keepNotifications */);
if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
if (at_eos) {
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index c13d6cb..0985f47 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -250,7 +250,7 @@
void notifyVideoSize_l();
void seekAudioIfNecessary_l();
- void cancelPlayerEvents(bool keepBufferingGoing = false);
+ void cancelPlayerEvents(bool keepNotifications = false);
void setAudioSource(sp<MediaSource> source);
status_t initAudioDecoder();
diff --git a/opengl/java/android/opengl/ManagedEGLContext.java b/opengl/java/android/opengl/ManagedEGLContext.java
new file mode 100644
index 0000000..d3a3662
--- /dev/null
+++ b/opengl/java/android/opengl/ManagedEGLContext.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.opengl;
+
+import static javax.microedition.khronos.egl.EGL10.EGL_DEFAULT_DISPLAY;
+import static javax.microedition.khronos.egl.EGL10.EGL_NO_DISPLAY;
+
+import java.util.ArrayList;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+
+import android.os.Looper;
+import android.util.Log;
+
+import com.google.android.gles_jni.EGLImpl;
+
+/**
+ * The per-process memory overhead of hardware accelerated graphics can
+ * be quite large on some devices. For small memory devices, being able to
+ * terminate all EGL contexts so that this graphics driver memory can be
+ * reclaimed can significant improve the overall behavior of the device. This
+ * class helps app developers participate in releasing their EGL context
+ * when appropriate and possible.
+ *
+ * <p>To use, simple instantiate this class with the EGLContext you create.
+ * When you have done this, if the device is getting low on memory and all
+ * of the currently created EGL contexts in the process are being managed
+ * through this class, then they will all be asked to terminate through the
+ * call to {@link #onTerminate}.
+ */
+public abstract class ManagedEGLContext {
+ static final String TAG = "ManagedEGLContext";
+
+ static final ArrayList<ManagedEGLContext> sActive
+ = new ArrayList<ManagedEGLContext>();
+
+ final EGLContext mContext;
+
+ /**
+ * Instantiate to manage the given EGLContext.
+ */
+ public ManagedEGLContext(EGLContext context) {
+ mContext = context;
+ synchronized (sActive) {
+ sActive.add(this);
+ }
+ }
+
+ /**
+ * Retrieve the EGLContext being managed by the class.
+ */
+ public EGLContext getContext() {
+ return mContext;
+ }
+
+ /**
+ * Force-terminate the ManagedEGLContext. This will cause
+ * {@link #onTerminate(EGLContext)} to be called. You <em>must</em>
+ * call this when destroying the EGLContext, so that the framework
+ * knows to stop managing it.
+ */
+ public void terminate() {
+ execTerminate();
+ }
+
+ void execTerminate() {
+ onTerminate(mContext);
+ }
+
+ /**
+ * Override this method to destroy the EGLContext when appropriate.
+ * <em>Note that this method is always called on the main thread
+ * of the process.</em> If your EGLContext was created on a different
+ * thread, you will need to implement this method to hand off the work
+ * of destroying the context to that thread.
+ */
+ public abstract void onTerminate(EGLContext context);
+
+ /** @hide */
+ public static boolean doTerminate() {
+ ArrayList<ManagedEGLContext> active;
+
+ if (Looper.getMainLooper() != Looper.myLooper()) {
+ throw new IllegalStateException("Called on wrong thread");
+ }
+
+ synchronized (sActive) {
+ // If there are no active managed contexts, we will not even
+ // try to terminate.
+ if (sActive.size() <= 0) {
+ return false;
+ }
+
+ // Need to check how many EGL contexts are actually running,
+ // to compare with how many we are managing.
+ EGL10 egl = (EGL10) EGLContext.getEGL();
+ EGLDisplay display = egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+ if (display == EGL_NO_DISPLAY) {
+ Log.w(TAG, "doTerminate failed: no display");
+ return false;
+ }
+
+ if (EGLImpl.getInitCount(display) != sActive.size()) {
+ Log.w(TAG, "doTerminate failed: EGL count is " + EGLImpl.getInitCount(display)
+ + " but managed count is " + sActive.size());
+ return false;
+ }
+
+ active = new ArrayList<ManagedEGLContext>(sActive);
+ sActive.clear();
+ }
+
+ for (int i=0; i<active.size(); i++) {
+ active.get(i).execTerminate();
+ }
+
+ return true;
+ }
+}
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 862b48d2..31119f9 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -220,15 +220,19 @@
if (end) {
// length of the extension string
const size_t len = end - start;
- // NOTE: we could avoid the copy if we had strnstr.
- const String8 ext(start, len);
- // now go through all implementations and look for this extension
- for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
- // if we find it, add this extension string to our list
- // (and don't forget the space)
- const char* match = strstr(disp[i].queryString.extensions, ext.string());
- if (match && (match[len] == ' ' || match[len] == 0)) {
- mExtensionString.append(start, len+1);
+ if (len) {
+ // NOTE: we could avoid the copy if we had strnstr.
+ const String8 ext(start, len);
+ // now go through all implementations and look for this extension
+ for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+ if (disp[i].queryString.extensions) {
+ // if we find it, add this extension string to our list
+ // (and don't forget the space)
+ const char* match = strstr(disp[i].queryString.extensions, ext.string());
+ if (match && (match[len] == ' ' || match[len] == 0)) {
+ mExtensionString.append(start, len+1);
+ }
+ }
}
}
// process the next extension string, and skip the space.
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 5495d08..aa08e64 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -723,6 +723,8 @@
upgradeVersion = 57;
}
+ /************* The following are Honeycomb changes ************/
+
if (upgradeVersion == 57) {
/*
* New settings to:
@@ -751,13 +753,13 @@
if (upgradeVersion == 58) {
/* Add default for new Auto Time Zone */
+ int autoTimeValue = getIntValueFromSystem(db, Settings.System.AUTO_TIME, 0);
db.beginTransaction();
SQLiteStatement stmt = null;
try {
- stmt = db.compileStatement("INSERT INTO secure(name,value)"
- + " VALUES(?,?);");
- loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
- R.bool.def_auto_time_zone); // Sync timezone to NITZ
+ stmt = db.compileStatement("INSERT INTO system(name,value)" + " VALUES(?,?);");
+ loadSetting(stmt, Settings.System.AUTO_TIME_ZONE,
+ autoTimeValue); // Sync timezone to NITZ if auto_time was enabled
db.setTransactionSuccessful();
} finally {
db.endTransaction();
@@ -784,18 +786,24 @@
}
if (upgradeVersion == 60) {
- upgradeScreenTimeout(db);
+ // Don't do this for upgrades from Gingerbread
+ // Were only required for intra-Honeycomb upgrades for testing
+ // upgradeScreenTimeout(db);
upgradeVersion = 61;
}
if (upgradeVersion == 61) {
- upgradeScreenTimeout(db);
+ // Don't do this for upgrades from Gingerbread
+ // Were only required for intra-Honeycomb upgrades for testing
+ // upgradeScreenTimeout(db);
upgradeVersion = 62;
}
// Change the default for screen auto-brightness mode
if (upgradeVersion == 62) {
- upgradeAutoBrightness(db);
+ // Don't do this for upgrades from Gingerbread
+ // Were only required for intra-Honeycomb upgrades for testing
+ // upgradeAutoBrightness(db);
upgradeVersion = 63;
}
@@ -839,6 +847,8 @@
upgradeVersion = 65;
}
+ /************* The following are Ice Cream Sandwich changes ************/
+
if (upgradeVersion == 65) {
/*
* Animations are removed from Settings. Turned on by default
@@ -1232,12 +1242,13 @@
stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+ " VALUES(?,?);");
- // Vibrate off by default for ringer, on for notification
+ // Vibrate on by default for ringer, on for notification
int vibrate = 0;
vibrate = AudioService.getValueForVibrateSetting(vibrate,
- AudioManager.VIBRATE_TYPE_NOTIFICATION, AudioManager.VIBRATE_SETTING_ON);
+ AudioManager.VIBRATE_TYPE_NOTIFICATION,
+ AudioManager.VIBRATE_SETTING_ONLY_SILENT);
vibrate |= AudioService.getValueForVibrateSetting(vibrate,
- AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_OFF);
+ AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_ONLY_SILENT);
loadSetting(stmt, Settings.System.VIBRATE_ON, vibrate);
} finally {
if (stmt != null) stmt.close();
@@ -1509,4 +1520,20 @@
loadSetting(stmt, key,
Float.toString(mContext.getResources().getFraction(resid, base, base)));
}
+
+ private int getIntValueFromSystem(SQLiteDatabase db, String name, int defaultValue) {
+ int value = defaultValue;
+ Cursor c = null;
+ try {
+ c = db.query("system", new String[] { Settings.System.VALUE }, "name='" + name + "'",
+ null, null, null, null);
+ if (c != null && c.moveToFirst()) {
+ String val = c.getString(0);
+ value = val == null ? defaultValue : Integer.parseInt(val);
+ }
+ } finally {
+ if (c != null) c.close();
+ }
+ return value;
+ }
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index eefb9fe..dff41c9 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -46,16 +46,26 @@
</intent-filter>
</receiver>
- <!-- handle dock insertion, launch screensaver instead -->
+ <!-- should you need to launch the screensaver, this is a good way to do it -->
<activity android:name=".DreamsDockLauncher"
+ android:theme="@android:style/Theme.Dialog"
android:label="@string/dreams_dock_launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.DESK_DOCK" />
</intent-filter>
</activity>
+ <!-- launch screensaver on (desk) dock event -->
+ <receiver android:name=".DreamsDockLauncher$DockEventReceiver"
+ android:exported="true"
+ >
+ <intent-filter>
+ <action android:name="android.intent.action.DOCK_EVENT" />
+ </intent-filter>
+ </receiver>
+
+
<activity android:name=".usb.UsbStorageActivity"
android:excludeFromRecents="true">
</activity>
@@ -124,7 +134,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.DREAM" />
+<!-- <category android:name="android.intent.category.DREAM" />-->
</intent-filter>
</activity>
</application>
diff --git a/packages/SystemUI/res/values-sw600dp/donottranslate.xml b/packages/SystemUI/res/values-sw600dp/donottranslate.xml
new file mode 100644
index 0000000..0996067
--- /dev/null
+++ b/packages/SystemUI/res/values-sw600dp/donottranslate.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2011, 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- For formatting day of week and date in DateView. %1$s is DOW, %2$s is date.
+ We show both (DOW on one line, then the date) but this can be overridden for locales as
+ necessary.
+ -->
+ <string name="status_bar_date_formatter">%1$s\n%2$s</string>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index 089a54d..4ca2116 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -21,6 +21,6 @@
We show both (DOW on one line, then the date) but this can be overridden for locales as
necessary.
-->
- <string name="status_bar_date_formatter">%1$s\n%2$s</string>
+ <string name="status_bar_date_formatter">%2$s</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
index b8cdd73..0035296 100644
--- a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
+++ b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
@@ -12,12 +12,23 @@
public class DreamsDockLauncher extends Activity {
private static final String TAG = "DreamsDockLauncher";
+
+ // Launch the screen saver if started as an activity.
@Override
protected void onCreate (Bundle icicle) {
super.onCreate(icicle);
+ launchDream(this);
+ finish();
+ }
+
+ private static void launchDream(Context context) {
try {
String component = Settings.Secure.getString(
- getContentResolver(), Settings.Secure.DREAM_COMPONENT);
+ context.getContentResolver(), Settings.Secure.DREAM_COMPONENT);
+ if (component == null) {
+ component = context.getResources().getString(
+ com.android.internal.R.string.config_defaultDreamComponent);
+ }
if (component != null) {
ComponentName cn = ComponentName.unflattenFromString(component);
Intent zzz = new Intent(Intent.ACTION_MAIN)
@@ -26,7 +37,8 @@
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_NO_USER_ACTION
);
- startActivity(zzz);
+ Slog.v(TAG, "Starting screen saver on dock event: " + component);
+ context.startActivity(zzz);
} else {
Slog.e(TAG, "Couldn't start screen saver: none selected");
}
@@ -34,6 +46,22 @@
// no screensaver? give up
Slog.e(TAG, "Couldn't start screen saver: none installed");
}
- finish();
+ }
+
+ // Trap low-level dock events and launch the screensaver.
+ public static class DockEventReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
+ Bundle extras = intent.getExtras();
+ int state = extras
+ .getInt(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
+ if (state == Intent.EXTRA_DOCK_STATE_DESK
+ || state == Intent.EXTRA_DOCK_STATE_LE_DESK
+ || state == Intent.EXTRA_DOCK_STATE_HE_DESK) {
+ launchDream(context);
+ }
+ }
+ }
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b4dd07b..e00a54c 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -157,6 +157,11 @@
static final boolean SHOW_STARTING_ANIMATIONS = true;
static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
+ // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
+ // No longer recommended for desk docks; still useful in car docks.
+ static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
+ static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
+
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
@@ -3420,6 +3425,9 @@
try {
String component = Settings.Secure.getString(
mContext.getContentResolver(), Settings.Secure.DREAM_COMPONENT);
+ if (component == null) {
+ component = mContext.getResources().getString(R.string.config_defaultDreamComponent);
+ }
if (component != null) {
ComponentName cn = ComponentName.unflattenFromString(component);
Intent intent = new Intent(Intent.ACTION_MAIN)
@@ -3508,21 +3516,35 @@
}
/**
- * Return an Intent to launch the currently active dock as home. Returns
- * null if the standard home should be launched.
+ * Return an Intent to launch the currently active dock app as home. Returns
+ * null if the standard home should be launched, which is the case if any of the following is
+ * true:
+ * <ul>
+ * <li>The device is not in either car mode or desk mode
+ * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
+ * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
+ * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
+ * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
+ * </ul>
* @return
*/
Intent createHomeDockIntent() {
- Intent intent;
+ Intent intent = null;
// What home does is based on the mode, not the dock state. That
// is, when in car mode you should be taken to car home regardless
// of whether we are actually in a car dock.
if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
- intent = mCarDockIntent;
+ if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
+ intent = mCarDockIntent;
+ }
} else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
- intent = mDeskDockIntent;
- } else {
+ if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
+ intent = mDeskDockIntent;
+ }
+ }
+
+ if (intent == null) {
return null;
}
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index a7eff93..5408436 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -142,5 +142,5 @@
# ---------------------------
# NetworkStatsService.java
# ---------------------------
-51100 netstats_mobile_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3)
-51101 netstats_wifi_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3)
+51100 netstats_mobile_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3),(dev_history_start|2|3)
+51101 netstats_wifi_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3),(dev_history_start|2|3)
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index af9152d..d04b440 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -360,7 +360,7 @@
}
final String sciId = info.getId();
final InternalServiceConnection connection = new InternalServiceConnection(
- sciId, locale, scListener, bundle);
+ sciId, locale, bundle);
final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE);
serviceIntent.setComponent(info.getComponent());
if (DBG) {
@@ -704,15 +704,13 @@
}
private class InternalServiceConnection implements ServiceConnection {
- private final ISpellCheckerSessionListener mListener;
private final String mSciId;
private final String mLocale;
private final Bundle mBundle;
public InternalServiceConnection(
- String id, String locale, ISpellCheckerSessionListener listener, Bundle bundle) {
+ String id, String locale, Bundle bundle) {
mSciId = id;
mLocale = locale;
- mListener = listener;
mBundle = bundle;
}
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 280b329..e6392d7 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -63,6 +63,10 @@
private static final String KEY_LAST_UPDATE_INTERVAL = "LAST_UPDATE_INTERVAL";
+ // Enable launching of applications when entering the dock.
+ private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
+ private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = false;
+
private static final int MSG_UPDATE_TWILIGHT = 0;
private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
private static final int MSG_GET_NEW_LOCATION_UPDATE = 2;
@@ -139,14 +143,16 @@
if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
// Only launch car home when car mode is enabled and the caller
// has asked us to switch to it.
- if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+ if (ENABLE_LAUNCH_CAR_DOCK_APP
+ && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
category = Intent.CATEGORY_CAR_DOCK;
}
} else if (UiModeManager.ACTION_ENTER_DESK_MODE.equals(intent.getAction())) {
// Only launch car home when desk mode is enabled and the caller
// has asked us to switch to it. Currently re-using the car
// mode flag since we don't have a formal API for "desk mode".
- if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+ if (ENABLE_LAUNCH_DESK_DOCK_APP
+ && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
category = Intent.CATEGORY_DESK_DOCK;
}
} else {
@@ -550,11 +556,13 @@
} else {
Intent homeIntent = null;
if (mCarModeEnabled) {
- if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+ if (ENABLE_LAUNCH_CAR_DOCK_APP
+ && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
homeIntent = buildHomeIntent(Intent.CATEGORY_CAR_DOCK);
}
} else if (isDeskDockState(mDockState)) {
- if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+ if (ENABLE_LAUNCH_DESK_DOCK_APP
+ && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
homeIntent = buildHomeIntent(Intent.CATEGORY_DESK_DOCK);
}
} else {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c0af2f6..8023477 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1251,11 +1251,11 @@
String[] emptyArgs = new String[] { };
StringBuilder tag = new StringBuilder(128);
synchronized (ActivityManagerService.this) {
- dumpProcessesLocked(null, catPw, emptyArgs, 0, false);
+ dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
catPw.println();
- dumpServicesLocked(null, catPw, emptyArgs, 0, false, false);
+ dumpServicesLocked(null, catPw, emptyArgs, 0, false, false, null);
catPw.println();
- dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false);
+ dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
catPw.println();
}
tag.append("Low on memory -- ");
@@ -1681,7 +1681,9 @@
final void setFocusedActivityLocked(ActivityRecord r) {
if (mFocusedActivity != r) {
mFocusedActivity = r;
- mWindowManager.setFocusedApp(r.appToken, true);
+ if (r != null) {
+ mWindowManager.setFocusedApp(r.appToken, true);
+ }
}
}
@@ -7907,6 +7909,7 @@
boolean dumpAll = false;
boolean dumpClient = false;
+ String dumpPackage = null;
int opti = 0;
while (opti < args.length) {
@@ -7924,13 +7927,14 @@
pw.println(" [-a] [-c] [-h] [cmd] ...");
pw.println(" cmd may be one of:");
pw.println(" a[ctivities]: activity stack state");
- pw.println(" b[roadcasts]: broadcast state");
- pw.println(" i[ntents]: pending intent state");
- pw.println(" p[rocesses]: process state");
+ pw.println(" b[roadcasts] [PACKAGE_NAME]: broadcast state");
+ pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state");
+ pw.println(" p[rocesses] [PACKAGE_NAME]: process state");
pw.println(" o[om]: out of memory management");
pw.println(" prov[iders] [COMP_SPEC ...]: content provider state");
pw.println(" s[ervices] [COMP_SPEC ...]: service state");
pw.println(" service [COMP_SPEC]: service client-side state");
+ pw.println(" package [PACKAGE_NAME]: all state related to given package");
pw.println(" all: dump all activities");
pw.println(" top: dump the top activity");
pw.println(" cmd may also be a COMP_SPEC to dump activities.");
@@ -7951,22 +7955,58 @@
opti++;
if ("activities".equals(cmd) || "a".equals(cmd)) {
synchronized (this) {
- dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
+ dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient, null);
}
return;
} else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
+ String[] newArgs;
+ String name;
+ if (opti >= args.length) {
+ name = null;
+ newArgs = EMPTY_STRING_ARRAY;
+ } else {
+ name = args[opti];
+ opti++;
+ newArgs = new String[args.length - opti];
+ if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
+ args.length - opti);
+ }
synchronized (this) {
- dumpBroadcastsLocked(fd, pw, args, opti, true);
+ dumpBroadcastsLocked(fd, pw, args, opti, true, name);
}
return;
} else if ("intents".equals(cmd) || "i".equals(cmd)) {
+ String[] newArgs;
+ String name;
+ if (opti >= args.length) {
+ name = null;
+ newArgs = EMPTY_STRING_ARRAY;
+ } else {
+ name = args[opti];
+ opti++;
+ newArgs = new String[args.length - opti];
+ if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
+ args.length - opti);
+ }
synchronized (this) {
- dumpPendingIntentsLocked(fd, pw, args, opti, true);
+ dumpPendingIntentsLocked(fd, pw, args, opti, true, name);
}
return;
} else if ("processes".equals(cmd) || "p".equals(cmd)) {
+ String[] newArgs;
+ String name;
+ if (opti >= args.length) {
+ name = null;
+ newArgs = EMPTY_STRING_ARRAY;
+ } else {
+ name = args[opti];
+ opti++;
+ newArgs = new String[args.length - opti];
+ if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
+ args.length - opti);
+ }
synchronized (this) {
- dumpProcessesLocked(fd, pw, args, opti, true);
+ dumpProcessesLocked(fd, pw, args, opti, true, name);
}
return;
} else if ("oom".equals(cmd) || "o".equals(cmd)) {
@@ -7976,7 +8016,7 @@
return;
} else if ("providers".equals(cmd) || "prov".equals(cmd)) {
synchronized (this) {
- dumpProvidersLocked(fd, pw, args, opti, true);
+ dumpProvidersLocked(fd, pw, args, opti, true, null);
}
return;
} else if ("service".equals(cmd)) {
@@ -7989,16 +8029,32 @@
name = args[opti];
opti++;
newArgs = new String[args.length - opti];
- if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
+ if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
+ args.length - opti);
}
if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
pw.println("No services match: " + name);
pw.println("Use -h for help.");
}
return;
+ } else if ("package".equals(cmd)) {
+ String[] newArgs;
+ if (opti >= args.length) {
+ pw.println("package: no package name specified");
+ pw.println("Use -h for help.");
+ return;
+ } else {
+ dumpPackage = args[opti];
+ opti++;
+ newArgs = new String[args.length - opti];
+ if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
+ args.length - opti);
+ args = newArgs;
+ opti = 0;
+ }
} else if ("services".equals(cmd) || "s".equals(cmd)) {
synchronized (this) {
- dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
+ dumpServicesLocked(fd, pw, args, opti, true, dumpClient, null);
}
return;
} else {
@@ -8014,76 +8070,78 @@
// No piece of data specified, dump everything.
synchronized (this) {
boolean needSep;
- needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
+ needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
if (needSep) {
pw.println(" ");
}
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
+ needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
if (needSep) {
pw.println(" ");
}
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
+ needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
if (needSep) {
pw.println(" ");
}
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
+ needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
if (needSep) {
pw.println(" ");
}
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
+ needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
if (needSep) {
pw.println(" ");
}
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- dumpProcessesLocked(fd, pw, args, opti, dumpAll);
+ dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage);
}
}
boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll, boolean dumpClient) {
+ int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
pw.println(" Main stack:");
- dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
+ dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient,
+ dumpPackage);
pw.println(" ");
pw.println(" Running activities (most recent first):");
- dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
+ dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false,
+ dumpPackage);
if (mMainStack.mWaitingVisibleActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting for another to become visible:");
dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
- !dumpAll, false);
+ !dumpAll, false, dumpPackage);
}
if (mMainStack.mStoppingActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting to stop:");
dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
- !dumpAll, false);
+ !dumpAll, false, dumpPackage);
}
if (mMainStack.mGoingToSleepActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting to sleep:");
dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
- !dumpAll, false);
+ !dumpAll, false, dumpPackage);
}
if (mMainStack.mFinishingActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting to finish:");
dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
- !dumpAll, false);
+ !dumpAll, false, dumpPackage);
}
pw.println(" ");
@@ -8106,6 +8164,12 @@
final int N = mRecentTasks.size();
for (int i=0; i<N; i++) {
TaskRecord tr = mRecentTasks.get(i);
+ if (dumpPackage != null) {
+ if (tr.realActivity == null ||
+ !dumpPackage.equals(tr.realActivity)) {
+ continue;
+ }
+ }
pw.print(" * Recent #"); pw.print(i); pw.print(": ");
pw.println(tr);
if (dumpAll) {
@@ -8123,7 +8187,7 @@
}
boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll) {
+ int opti, boolean dumpAll, String dumpPackage) {
boolean needSep = false;
int numPers = 0;
@@ -8133,11 +8197,14 @@
for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
final int NA = procs.size();
for (int ia=0; ia<NA; ia++) {
+ ProcessRecord r = procs.valueAt(ia);
+ if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+ continue;
+ }
if (!needSep) {
pw.println(" All known processes:");
needSep = true;
}
- ProcessRecord r = procs.valueAt(ia);
pw.print(r.persistent ? " *PERS*" : " *APP*");
pw.print(" UID "); pw.print(procs.keyAt(ia));
pw.print(" "); pw.println(r);
@@ -8154,31 +8221,49 @@
needSep = true;
pw.println(" Process LRU list (sorted by oom_adj):");
dumpProcessOomList(pw, this, mLruProcesses, " ",
- "Proc", "PERS", false);
+ "Proc", "PERS", false, dumpPackage);
needSep = true;
}
if (dumpAll) {
synchronized (mPidsSelfLocked) {
- if (mPidsSelfLocked.size() > 0) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" PID mappings:");
- for (int i=0; i<mPidsSelfLocked.size(); i++) {
- pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
- pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
+ boolean printed = false;
+ for (int i=0; i<mPidsSelfLocked.size(); i++) {
+ ProcessRecord r = mPidsSelfLocked.valueAt(i);
+ if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+ continue;
}
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" PID mappings:");
+ printed = true;
+ }
+ pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
+ pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
}
}
}
if (mForegroundProcesses.size() > 0) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Foreground Processes:");
- for (int i=0; i<mForegroundProcesses.size(); i++) {
- pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
- pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
+ synchronized (mPidsSelfLocked) {
+ boolean printed = false;
+ for (int i=0; i<mForegroundProcesses.size(); i++) {
+ ProcessRecord r = mPidsSelfLocked.get(
+ mForegroundProcesses.valueAt(i).pid);
+ if (dumpPackage != null && (r == null
+ || !dumpPackage.equals(r.info.packageName))) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Foreground Processes:");
+ printed = true;
+ }
+ pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
+ pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
+ }
}
}
@@ -8187,7 +8272,7 @@
needSep = true;
pw.println(" Persisent processes that are starting:");
dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
- "Starting Norm", "Restarting PERS");
+ "Starting Norm", "Restarting PERS", dumpPackage);
}
if (mRemovedProcesses.size() > 0) {
@@ -8195,7 +8280,7 @@
needSep = true;
pw.println(" Processes that are being removed:");
dumpProcessList(pw, this, mRemovedProcesses, " ",
- "Removed Norm", "Removed PERS");
+ "Removed Norm", "Removed PERS", dumpPackage);
}
if (mProcessesOnHold.size() > 0) {
@@ -8203,23 +8288,34 @@
needSep = true;
pw.println(" Processes that are on old until the system is ready:");
dumpProcessList(pw, this, mProcessesOnHold, " ",
- "OnHold Norm", "OnHold PERS");
+ "OnHold Norm", "OnHold PERS", dumpPackage);
}
- needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
+ needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, dumpPackage);
if (mProcessCrashTimes.getMap().size() > 0) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Time since processes crashed:");
+ boolean printed = false;
long now = SystemClock.uptimeMillis();
for (Map.Entry<String, SparseArray<Long>> procs
: mProcessCrashTimes.getMap().entrySet()) {
+ String pname = procs.getKey();
SparseArray<Long> uids = procs.getValue();
final int N = uids.size();
for (int i=0; i<N; i++) {
- pw.print(" Process "); pw.print(procs.getKey());
- pw.print(" uid "); pw.print(uids.keyAt(i));
+ int puid = uids.keyAt(i);
+ ProcessRecord r = mProcessNames.get(pname, puid);
+ if (dumpPackage != null && (r == null
+ || !dumpPackage.equals(r.info.packageName))) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Time since processes crashed:");
+ printed = true;
+ }
+ pw.print(" Process "); pw.print(pname);
+ pw.print(" uid "); pw.print(puid);
pw.print(": last crashed ");
pw.print((now-uids.valueAt(i)));
pw.println(" ms ago");
@@ -8228,16 +8324,26 @@
}
if (mBadProcesses.getMap().size() > 0) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Bad processes:");
+ boolean printed = false;
for (Map.Entry<String, SparseArray<Long>> procs
: mBadProcesses.getMap().entrySet()) {
+ String pname = procs.getKey();
SparseArray<Long> uids = procs.getValue();
final int N = uids.size();
for (int i=0; i<N; i++) {
- pw.print(" Bad process "); pw.print(procs.getKey());
- pw.print(" uid "); pw.print(uids.keyAt(i));
+ int puid = uids.keyAt(i);
+ ProcessRecord r = mProcessNames.get(pname, puid);
+ if (dumpPackage != null && (r == null
+ || !dumpPackage.equals(r.info.packageName))) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Bad processes:");
+ }
+ pw.print(" Bad process "); pw.print(pname);
+ pw.print(" uid "); pw.print(puid);
pw.print(": crashed at time ");
pw.println(uids.valueAt(i));
}
@@ -8254,11 +8360,18 @@
if (dumpAll) {
pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
if (mCompatModePackages.getPackages().size() > 0) {
- pw.println(" mScreenCompatPackages:");
+ boolean printed = false;
for (Map.Entry<String, Integer> entry
: mCompatModePackages.getPackages().entrySet()) {
String pkg = entry.getKey();
int mode = entry.getValue();
+ if (dumpPackage != null && !dumpPackage.equals(pkg)) {
+ continue;
+ }
+ if (!printed) {
+ pw.println(" mScreenCompatPackages:");
+ printed = true;
+ }
pw.print(" "); pw.print(pkg); pw.print(": ");
pw.print(mode); pw.println();
}
@@ -8307,14 +8420,21 @@
}
boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean needSep, boolean dumpAll) {
+ int opti, boolean needSep, boolean dumpAll, String dumpPackage) {
if (mProcessesToGc.size() > 0) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Processes that are waiting to GC:");
+ boolean printed = false;
long now = SystemClock.uptimeMillis();
for (int i=0; i<mProcessesToGc.size(); i++) {
ProcessRecord proc = mProcessesToGc.get(i);
+ if (dumpPackage != null && !dumpPackage.equals(proc.info.packageName)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Processes that are waiting to GC:");
+ printed = true;
+ }
pw.print(" Process "); pw.println(proc);
pw.print(" lowMem="); pw.print(proc.reportLowMemory);
pw.print(", last gced=");
@@ -8354,11 +8474,11 @@
needSep = true;
pw.println(" Process OOM control:");
dumpProcessOomList(pw, this, mLruProcesses, " ",
- "Proc", "PERS", true);
+ "Proc", "PERS", true, null);
needSep = true;
}
- needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
+ needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, null);
pw.println();
pw.println(" mHomeProcess: " + mHomeProcess);
@@ -8658,64 +8778,103 @@
}
boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll) {
+ int opti, boolean dumpAll, String dumpPackage) {
boolean needSep = false;
pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
if (dumpAll) {
if (mRegisteredReceivers.size() > 0) {
- pw.println(" Registered Receivers:");
+ boolean printed = false;
Iterator it = mRegisteredReceivers.values().iterator();
while (it.hasNext()) {
ReceiverList r = (ReceiverList)it.next();
+ if (dumpPackage != null && (r.app == null ||
+ !dumpPackage.equals(r.app.info.packageName))) {
+ continue;
+ }
+ if (!printed) {
+ pw.println(" Registered Receivers:");
+ needSep = true;
+ printed = true;
+ }
pw.print(" * "); pw.println(r);
r.dump(pw, " ");
}
}
-
- pw.println();
- pw.println(" Receiver Resolver Table:");
- mReceiverResolver.dump(pw, null, " ", null, false);
- needSep = true;
+
+ if (mReceiverResolver.dump(pw, needSep ?
+ "\n Receiver Resolver Table:" : " Receiver Resolver Table:",
+ " ", dumpPackage, false)) {
+ needSep = true;
+ }
}
if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
|| mPendingBroadcast != null) {
- if (mParallelBroadcasts.size() > 0) {
- pw.println();
- pw.println(" Active broadcasts:");
- }
+ boolean printed = false;
for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
+ BroadcastRecord br = mParallelBroadcasts.get(i);
+ if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) {
+ pw.println();
+ }
+ needSep = true;
+ pw.println(" Active broadcasts:");
+ }
pw.println(" Broadcast #" + i + ":");
- mParallelBroadcasts.get(i).dump(pw, " ");
+ br.dump(pw, " ");
}
- if (mOrderedBroadcasts.size() > 0) {
- pw.println();
- pw.println(" Active ordered broadcasts:");
- }
+ printed = false;
for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
- pw.println(" Serialized Broadcast #" + i + ":");
+ BroadcastRecord br = mOrderedBroadcasts.get(i);
+ if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) {
+ pw.println();
+ }
+ needSep = true;
+ pw.println(" Active ordered broadcasts:");
+ }
+ pw.println(" Ordered Broadcast #" + i + ":");
mOrderedBroadcasts.get(i).dump(pw, " ");
}
- pw.println();
- pw.println(" Pending broadcast:");
- if (mPendingBroadcast != null) {
- mPendingBroadcast.dump(pw, " ");
- } else {
- pw.println(" (null)");
+ if (dumpPackage == null || (mPendingBroadcast != null
+ && dumpPackage.equals(mPendingBroadcast.callerPackage))) {
+ if (needSep) {
+ pw.println();
+ }
+ pw.println(" Pending broadcast:");
+ if (mPendingBroadcast != null) {
+ mPendingBroadcast.dump(pw, " ");
+ } else {
+ pw.println(" (null)");
+ }
+ needSep = true;
}
- needSep = true;
}
- if (needSep) {
- pw.println();
- }
- pw.println(" Historical broadcasts:");
+ boolean printed = false;
for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
BroadcastRecord r = mBroadcastHistory[i];
if (r == null) {
break;
}
+ if (dumpPackage != null && !dumpPackage.equals(r.callerPackage)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) {
+ pw.println();
+ }
+ needSep = true;
+ pw.println(" Historical broadcasts:");
+ printed = true;
+ }
if (dumpAll) {
pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
r.dump(pw, " ");
@@ -8729,8 +8888,11 @@
}
needSep = true;
- if (mStickyBroadcasts != null) {
- pw.println();
+ if (mStickyBroadcasts != null && dumpPackage == null) {
+ if (needSep) {
+ pw.println();
+ }
+ needSep = true;
pw.println(" Sticky broadcasts:");
StringBuilder sb = new StringBuilder(128);
for (Map.Entry<String, ArrayList<Intent>> ent
@@ -8770,7 +8932,7 @@
}
boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll, boolean dumpClient) {
+ int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
boolean needSep = false;
ItemMatcher matcher = new ItemMatcher();
@@ -8778,7 +8940,7 @@
pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
if (mServices.size() > 0) {
- pw.println(" Active services:");
+ boolean printed = false;
long nowReal = SystemClock.elapsedRealtime();
Iterator<ServiceRecord> it = mServices.values().iterator();
needSep = false;
@@ -8787,6 +8949,13 @@
if (!matcher.match(r, r.name)) {
continue;
}
+ if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+ continue;
+ }
+ if (!printed) {
+ pw.println(" Active services:");
+ printed = true;
+ }
if (needSep) {
pw.println();
}
@@ -8838,17 +9007,25 @@
needSep = true;
}
}
- needSep = true;
+ needSep = printed;
}
if (mPendingServices.size() > 0) {
- if (needSep) pw.println(" ");
- pw.println(" Pending services:");
+ boolean printed = false;
for (int i=0; i<mPendingServices.size(); i++) {
ServiceRecord r = mPendingServices.get(i);
if (!matcher.match(r, r.name)) {
continue;
}
+ if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Pending services:");
+ printed = true;
+ }
pw.print(" * Pending "); pw.println(r);
r.dump(pw, " ");
}
@@ -8856,13 +9033,21 @@
}
if (mRestartingServices.size() > 0) {
- if (needSep) pw.println(" ");
- pw.println(" Restarting services:");
+ boolean printed = false;
for (int i=0; i<mRestartingServices.size(); i++) {
ServiceRecord r = mRestartingServices.get(i);
if (!matcher.match(r, r.name)) {
continue;
}
+ if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Restarting services:");
+ printed = true;
+ }
pw.print(" * Restarting "); pw.println(r);
r.dump(pw, " ");
}
@@ -8870,13 +9055,21 @@
}
if (mStoppingServices.size() > 0) {
- if (needSep) pw.println(" ");
- pw.println(" Stopping services:");
+ boolean printed = false;
for (int i=0; i<mStoppingServices.size(); i++) {
ServiceRecord r = mStoppingServices.get(i);
if (!matcher.match(r, r.name)) {
continue;
}
+ if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Stopping services:");
+ printed = true;
+ }
pw.print(" * Stopping "); pw.println(r);
r.dump(pw, " ");
}
@@ -8885,8 +9078,7 @@
if (dumpAll) {
if (mServiceConnections.size() > 0) {
- if (needSep) pw.println(" ");
- pw.println(" Connection bindings to services:");
+ boolean printed = false;
Iterator<ArrayList<ConnectionRecord>> it
= mServiceConnections.values().iterator();
while (it.hasNext()) {
@@ -8896,6 +9088,16 @@
if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
continue;
}
+ if (dumpPackage != null && (cr.binding.client == null
+ || !dumpPackage.equals(cr.binding.client.info.packageName))) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Connection bindings to services:");
+ printed = true;
+ }
pw.print(" * "); pw.println(cr);
cr.dump(pw, " ");
}
@@ -8908,7 +9110,7 @@
}
boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll) {
+ int opti, boolean dumpAll, String dumpPackage) {
boolean needSep = false;
ItemMatcher matcher = new ItemMatcher();
@@ -8916,8 +9118,7 @@
pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
if (mProvidersByClass.size() > 0) {
- if (needSep) pw.println(" ");
- pw.println(" Published content providers (by class):");
+ boolean printed = false;
Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it
= mProvidersByClass.entrySet().iterator();
while (it.hasNext()) {
@@ -8932,6 +9133,15 @@
if (!matcher.match(r, comp)) {
continue;
}
+ if (dumpPackage != null && !dumpPackage.equals(comp.getPackageName())) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Published content providers (by class):");
+ printed = true;
+ }
pw.print(" * "); pw.print(cls); pw.print(" (");
pw.print(comp.flattenToShortString()); pw.println(")");
if (dumpAll) {
@@ -8950,13 +9160,11 @@
}
}
}
- needSep = true;
}
if (dumpAll) {
if (mProvidersByName.size() > 0) {
- pw.println(" ");
- pw.println(" Authority to provider mappings:");
+ boolean printed = false;
Iterator<Map.Entry<String, ContentProviderRecord>> it
= mProvidersByName.entrySet().iterator();
while (it.hasNext()) {
@@ -8965,25 +9173,42 @@
if (!matcher.match(r, r.name)) {
continue;
}
+ if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Authority to provider mappings:");
+ printed = true;
+ }
pw.print(" "); pw.print(e.getKey()); pw.println(":");
pw.print(" "); pw.println(r);
}
- needSep = true;
}
}
if (mLaunchingProviders.size() > 0) {
- if (needSep) pw.println(" ");
- pw.println(" Launching content providers:");
+ boolean printed = false;
for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
+ ContentProviderRecord r = mLaunchingProviders.get(i);
+ if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Launching content providers:");
+ printed = true;
+ }
pw.print(" Launching #"); pw.print(i); pw.print(": ");
- pw.println(mLaunchingProviders.get(i));
+ pw.println(r);
}
- needSep = true;
}
if (mGrantedUriPermissions.size() > 0) {
- pw.println();
+ if (needSep) pw.println();
+ needSep = true;
pw.println("Granted Uri Permissions:");
for (int i=0; i<mGrantedUriPermissions.size(); i++) {
int uid = mGrantedUriPermissions.keyAt(i);
@@ -9005,16 +9230,24 @@
}
boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll) {
+ int opti, boolean dumpAll, String dumpPackage) {
boolean needSep = false;
- if (this.mIntentSenderRecords.size() > 0) {
- pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
+ if (mIntentSenderRecords.size() > 0) {
+ boolean printed = false;
Iterator<WeakReference<PendingIntentRecord>> it
= mIntentSenderRecords.values().iterator();
while (it.hasNext()) {
WeakReference<PendingIntentRecord> ref = it.next();
PendingIntentRecord rec = ref != null ? ref.get(): null;
+ if (dumpPackage != null && (rec == null
+ || !dumpPackage.equals(rec.key.packageName))) {
+ continue;
+ }
+ if (!printed) {
+ pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
+ printed = true;
+ }
needSep = true;
if (rec != null) {
pw.print(" * "); pw.println(rec);
@@ -9031,13 +9264,17 @@
}
private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
- String prefix, String label, boolean complete, boolean brief, boolean client) {
+ String prefix, String label, boolean complete, boolean brief, boolean client,
+ String dumpPackage) {
TaskRecord lastTask = null;
boolean needNL = false;
final String innerPrefix = prefix + " ";
final String[] args = new String[0];
for (int i=list.size()-1; i>=0; i--) {
final ActivityRecord r = (ActivityRecord)list.get(i);
+ if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
+ continue;
+ }
final boolean full = !brief && (complete || !r.isInHistory());
if (needNL) {
pw.println(" ");
@@ -9105,11 +9342,15 @@
private static final int dumpProcessList(PrintWriter pw,
ActivityManagerService service, List list,
- String prefix, String normalLabel, String persistentLabel) {
+ String prefix, String normalLabel, String persistentLabel,
+ String dumpPackage) {
int numPers = 0;
final int N = list.size()-1;
for (int i=N; i>=0; i--) {
ProcessRecord r = (ProcessRecord)list.get(i);
+ if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+ continue;
+ }
pw.println(String.format("%s%s #%2d: %s",
prefix, (r.persistent ? persistentLabel : normalLabel),
i, r.toString()));
@@ -9120,17 +9361,25 @@
return numPers;
}
- private static final void dumpProcessOomList(PrintWriter pw,
+ private static final boolean dumpProcessOomList(PrintWriter pw,
ActivityManagerService service, List<ProcessRecord> origList,
String prefix, String normalLabel, String persistentLabel,
- boolean inclDetails) {
+ boolean inclDetails, String dumpPackage) {
ArrayList<Pair<ProcessRecord, Integer>> list
= new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
for (int i=0; i<origList.size(); i++) {
+ ProcessRecord r = origList.get(i);
+ if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+ continue;
+ }
list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
}
+ if (list.size() <= 0) {
+ return false;
+ }
+
Comparator<Pair<ProcessRecord, Integer>> comparator
= new Comparator<Pair<ProcessRecord, Integer>>() {
@Override
@@ -9153,8 +9402,7 @@
final long curUptime = SystemClock.uptimeMillis();
final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
- final int N = list.size()-1;
- for (int i=N; i>=0; i--) {
+ for (int i=list.size()-1; i>=0; i--) {
ProcessRecord r = list.get(i).first;
String oomAdj;
if (r.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
@@ -9206,8 +9454,8 @@
}
pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
prefix, (r.persistent ? persistentLabel : normalLabel),
- N-list.get(i).second, oomAdj, schedGroup, foreground, r.trimMemoryLevel,
- r.toShortString(), r.adjType));
+ (origList.size()-1)-list.get(i).second, oomAdj, schedGroup,
+ foreground, r.trimMemoryLevel, r.toShortString(), r.adjType));
if (r.adjSource != null || r.adjTarget != null) {
pw.print(prefix);
pw.print(" ");
@@ -9279,6 +9527,7 @@
}
}
}
+ return true;
}
ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, int start, String[] args) {
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 2a1b1db..8c0f1e0 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -393,6 +393,7 @@
// on background handler thread, and verified
// READ_NETWORK_USAGE_HISTORY permission above.
+ maybeRefreshTrustedTime();
synchronized (mRulesLock) {
updateNetworkEnabledLocked();
updateNotificationsLocked();
@@ -445,7 +446,7 @@
// cycle boundary to recompute notifications.
// examine stats for each active policy
- final long currentTime = currentTimeMillis(true);
+ final long currentTime = currentTimeMillis();
for (NetworkPolicy policy : mNetworkPolicy.values()) {
// ignore policies that aren't relevant to user
if (!isTemplateRelevant(policy.template)) continue;
@@ -683,6 +684,8 @@
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified CONNECTIVITY_INTERNAL
// permission above.
+
+ maybeRefreshTrustedTime();
synchronized (mRulesLock) {
ensureActiveMobilePolicyLocked();
updateNetworkEnabledLocked();
@@ -702,7 +705,7 @@
// TODO: reset any policy-disabled networks when any policy is removed
// completely, which is currently rare case.
- final long currentTime = currentTimeMillis(true);
+ final long currentTime = currentTimeMillis();
for (NetworkPolicy policy : mNetworkPolicy.values()) {
// shortcut when policy has no limit
if (policy.limitBytes == LIMIT_DISABLED) {
@@ -802,7 +805,7 @@
// apply each policy that we found ifaces for; compute remaining data
// based on current cycle and historical stats, and push to kernel.
- final long currentTime = currentTimeMillis(true);
+ final long currentTime = currentTimeMillis();
for (NetworkPolicy policy : mNetworkRules.keySet()) {
final String[] ifaces = mNetworkRules.get(policy);
@@ -1092,6 +1095,7 @@
public void setNetworkPolicies(NetworkPolicy[] policies) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+ maybeRefreshTrustedTime();
synchronized (mRulesLock) {
mNetworkPolicy.clear();
for (NetworkPolicy policy : policies) {
@@ -1119,7 +1123,8 @@
public void snoozePolicy(NetworkTemplate template) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
- final long currentTime = currentTimeMillis(true);
+ maybeRefreshTrustedTime();
+ final long currentTime = currentTimeMillis();
synchronized (mRulesLock) {
// find and snooze local policy that matches
final NetworkPolicy policy = mNetworkPolicy.get(template);
@@ -1140,6 +1145,7 @@
public void setRestrictBackground(boolean restrictBackground) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+ maybeRefreshTrustedTime();
synchronized (mRulesLock) {
mRestrictBackground = restrictBackground;
updateRulesForRestrictBackgroundLocked();
@@ -1193,7 +1199,7 @@
return null;
}
- final long currentTime = currentTimeMillis(false);
+ final long currentTime = currentTimeMillis();
// find total bytes used under policy
final long start = computeLastCycleBoundary(currentTime, policy);
@@ -1472,6 +1478,7 @@
case MSG_LIMIT_REACHED: {
final String iface = (String) msg.obj;
+ maybeRefreshTrustedTime();
synchronized (mRulesLock) {
if (mMeteredIfaces.contains(iface)) {
try {
@@ -1551,12 +1558,16 @@
}
}
- private long currentTimeMillis(boolean allowRefresh) {
- // try refreshing time source when stale
- if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE && allowRefresh) {
+ /**
+ * Try refreshing {@link #mTime} when stale.
+ */
+ private void maybeRefreshTrustedTime() {
+ if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
mTime.forceRefresh();
}
+ }
+ private long currentTimeMillis() {
return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
}
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 28cb983..871ed68 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -203,6 +203,8 @@
/** Set of historical {@code xtables} stats for known UIDs. */
private HashMap<UidStatsKey, NetworkStatsHistory> mUidStats = Maps.newHashMap();
+ /** Flag if {@link #mNetworkDevStats} have been loaded from disk. */
+ private boolean mNetworkStatsLoaded = false;
/** Flag if {@link #mUidStats} have been loaded from disk. */
private boolean mUidStatsLoaded = false;
@@ -272,6 +274,7 @@
// until actually needed.
readNetworkDevStatsLocked();
readNetworkXtStatsLocked();
+ mNetworkStatsLoaded = true;
}
// bootstrap initial stats to prevent double-counting later
@@ -322,14 +325,17 @@
mTeleManager.listen(mPhoneListener, LISTEN_NONE);
- writeNetworkDevStatsLocked();
- writeNetworkXtStatsLocked();
+ if (mNetworkStatsLoaded) {
+ writeNetworkDevStatsLocked();
+ writeNetworkXtStatsLocked();
+ }
if (mUidStatsLoaded) {
writeUidStatsLocked();
}
mNetworkDevStats.clear();
mNetworkXtStats.clear();
mUidStats.clear();
+ mNetworkStatsLoaded = false;
mUidStatsLoaded = false;
}
@@ -472,6 +478,18 @@
}
}
+ private long getHistoryStartLocked(
+ NetworkTemplate template, HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
+ long start = Long.MAX_VALUE;
+ for (NetworkIdentitySet ident : source.keySet()) {
+ if (templateMatches(template, ident)) {
+ final NetworkStatsHistory history = source.get(ident);
+ start = Math.min(start, history.getStart());
+ }
+ }
+ return start;
+ }
+
@Override
public NetworkStats getSummaryForAllUid(
NetworkTemplate template, long start, long end, boolean includeTags) {
@@ -771,6 +789,12 @@
private void performPoll(int flags) {
synchronized (mStatsLock) {
mWakeLock.acquire();
+
+ // try refreshing time source when stale
+ if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
+ mTime.forceRefresh();
+ }
+
try {
performPollLocked(flags);
} finally {
@@ -791,11 +815,6 @@
final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
- // try refreshing time source when stale
- if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
- mTime.forceRefresh();
- }
-
// TODO: consider marking "untrusted" times in historical stats
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
@@ -981,6 +1000,7 @@
final long start = end - largestBucketSize;
final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
+ long devHistoryStart = Long.MAX_VALUE;
NetworkTemplate template = null;
NetworkStats.Entry devTotal = null;
@@ -990,24 +1010,27 @@
// collect mobile sample
template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal);
+ devHistoryStart = getHistoryStartLocked(template, mNetworkDevStats);
xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal);
uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
+
EventLogTags.writeNetstatsMobileSample(
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
- trustedTime);
+ trustedTime, devHistoryStart);
// collect wifi sample
template = buildTemplateWifi();
devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal);
+ devHistoryStart = getHistoryStartLocked(template, mNetworkDevStats);
xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal);
uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
EventLogTags.writeNetstatsWifiSample(
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
- trustedTime);
+ trustedTime, devHistoryStart);
}
/**
@@ -1243,11 +1266,28 @@
// trim any history beyond max
if (mTime.hasCache()) {
- final long currentTime = Math.min(
- System.currentTimeMillis(), mTime.currentTimeMillis());
+ final long systemCurrentTime = System.currentTimeMillis();
+ final long trustedCurrentTime = mTime.currentTimeMillis();
+
+ final long currentTime = Math.min(systemCurrentTime, trustedCurrentTime);
final long maxHistory = mSettings.getNetworkMaxHistory();
+
for (NetworkStatsHistory history : input.values()) {
+ final int beforeSize = history.size();
history.removeBucketsBefore(currentTime - maxHistory);
+ final int afterSize = history.size();
+
+ if (beforeSize > 24 && afterSize < beforeSize / 2) {
+ // yikes, dropping more than half of significant history
+ final StringBuilder builder = new StringBuilder();
+ builder.append("yikes, dropping more than half of history").append('\n');
+ builder.append("systemCurrentTime=").append(systemCurrentTime).append('\n');
+ builder.append("trustedCurrentTime=").append(trustedCurrentTime).append('\n');
+ builder.append("maxHistory=").append(maxHistory).append('\n');
+ builder.append("beforeSize=").append(beforeSize).append('\n');
+ builder.append("afterSize=").append(afterSize).append('\n');
+ mDropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
+ }
}
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 0e9f64c..7005541 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -7947,7 +7947,7 @@
if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
boolean printedSomething = false;
- for (PackageParser.Provider p : mProviders.values()) {
+ for (PackageParser.Provider p : mProvidersByComponent.values()) {
if (packageName != null && !packageName.equals(p.info.packageName)) {
continue;
}
@@ -7957,8 +7957,23 @@
pw.println("Registered ContentProviders:");
printedSomething = true;
}
- pw.print(" ["); pw.print(p.info.authority); pw.print("]: ");
- pw.println(p.toString());
+ pw.print(" "); pw.print(p.getComponentShortName()); pw.println(":");
+ pw.print(" "); pw.println(p.toString());
+ }
+ printedSomething = false;
+ for (Map.Entry<String, PackageParser.Provider> entry : mProviders.entrySet()) {
+ PackageParser.Provider p = entry.getValue();
+ if (packageName != null && !packageName.equals(p.info.packageName)) {
+ continue;
+ }
+ if (!printedSomething) {
+ if (dumpState.onTitlePrinted())
+ pw.println(" ");
+ pw.println("ContentProvider Authorities:");
+ printedSomething = true;
+ }
+ pw.print(" ["); pw.print(entry.getKey()); pw.println("]:");
+ pw.print(" "); pw.println(p.toString());
}
}
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 53502db..61a8358 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -30,10 +30,6 @@
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
endif
-ifneq (,$(findstring $(TARGET_DEVICE),tuna toro maguro))
- LOCAL_CFLAGS += -DREFRESH_RATE=59
-endif
-
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 0618374..7c61e9a 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -693,12 +693,13 @@
expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
expectMeteredIfacesChanged(TEST_IFACE);
- expectClearNotifications();
+ future = expectClearNotifications();
tagFuture = expectEnqueueNotification();
replay();
mService.snoozePolicy(sTemplateWifi);
assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
+ future.get();
verifyAndReset();
}
}
@@ -734,9 +735,11 @@
expectLastCall().atLeastOnce();
}
- private void expectClearNotifications() throws Exception {
+ private Future<Void> expectClearNotifications() throws Exception {
+ final FutureAnswer future = new FutureAnswer();
mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
- expectLastCall().anyTimes();
+ expectLastCall().andAnswer(future).anyTimes();
+ return future;
}
private Future<String> expectEnqueueNotification() throws Exception {
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index f2ccb5b..56a0a2c 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1575,6 +1575,17 @@
// If the number passed in is null, just return false:
if (number == null) return false;
+ // If the number passed in is a SIP address, return false, since the
+ // concept of "emergency numbers" is only meaningful for calls placed
+ // over the cell network.
+ // (Be sure to do this check *before* calling extractNetworkPortionAlt(),
+ // since the whole point of extractNetworkPortionAlt() is to filter out
+ // any non-dialable characters (which would turn 'abc911def@example.com'
+ // into '911', for example.))
+ if (isUriNumber(number)) {
+ return false;
+ }
+
// Strip the separators from the number before comparing it
// to the list.
number = extractNetworkPortionAlt(number);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8ead45e..db78e2e 100755
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -60,16 +60,16 @@
/** @hide */
public TelephonyManager(Context context) {
- context = context.getApplicationContext();
if (sContext == null) {
- sContext = context;
+ Context appContext = context.getApplicationContext();
+ if (appContext != null) {
+ sContext = appContext;
+ } else {
+ sContext = context;
+ }
sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry"));
- } else if (sContext != context) {
- Log.e(TAG, "Hidden constructor called more than once per process!");
- Log.e(TAG, "Original: " + sContext.getPackageName() + ", new: " +
- context.getPackageName());
}
}