diff options
| -rw-r--r-- | core/java/android/view/ScaleGestureDetector.java | 37 | ||||
| -rw-r--r-- | core/java/android/webkit/DebugFlags.java | 2 | ||||
| -rw-r--r-- | core/java/android/webkit/WebView.java | 236 | ||||
| -rw-r--r-- | core/jni/android/graphics/Canvas.cpp | 42 | ||||
| -rw-r--r-- | core/jni/android/graphics/Typeface.cpp | 2 | ||||
| -rw-r--r-- | docs/html/guide/developing/debug-tasks.jd | 26 | ||||
| -rw-r--r-- | graphics/java/android/graphics/utils/BoundaryPatch.java | 173 | ||||
| -rw-r--r-- | services/java/com/android/server/ConnectivityService.java | 45 | ||||
| -rw-r--r-- | services/java/com/android/server/WifiService.java | 11 |
9 files changed, 529 insertions, 45 deletions
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java index 50bfefc..2f1c2b2 100644 --- a/core/java/android/view/ScaleGestureDetector.java +++ b/core/java/android/view/ScaleGestureDetector.java @@ -185,12 +185,16 @@ public class ScaleGestureDetector { final float x1 = getRawX(event, 1); final float y1 = getRawY(event, 1); - boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || - x1 < edgeSlop || y1 < edgeSlop; - boolean p1sloppy = x0 > rightSlop || y0 > bottomSlop || - x1 > rightSlop || y1 > bottomSlop; - - if (p0sloppy) { + boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop + || x0 > rightSlop || y0 > bottomSlop; + boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop + || x1 > rightSlop || y1 > bottomSlop; + + if(p0sloppy && p1sloppy) { + mFocusX = -1; + mFocusY = -1; + mSloppyGesture = true; + } else if (p0sloppy) { mFocusX = event.getX(1); mFocusY = event.getY(1); mSloppyGesture = true; @@ -211,12 +215,15 @@ public class ScaleGestureDetector { final float x1 = getRawX(event, 1); final float y1 = getRawY(event, 1); - boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || - x1 < edgeSlop || y1 < edgeSlop; - boolean p1sloppy = x0 > rightSlop || y0 > bottomSlop || - x1 > rightSlop || y1 > bottomSlop; + boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop + || x0 > rightSlop || y0 > bottomSlop; + boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop + || x1 > rightSlop || y1 > bottomSlop; - if (p0sloppy) { + if(p0sloppy && p1sloppy) { + mFocusX = -1; + mFocusY = -1; + } else if (p0sloppy) { mFocusX = event.getX(1); mFocusY = event.getY(1); } else if (p1sloppy) { @@ -226,6 +233,14 @@ public class ScaleGestureDetector { mSloppyGesture = false; mGestureInProgress = mListener.onScaleBegin(this); } + } else if ((action == MotionEvent.ACTION_POINTER_1_UP + || action == MotionEvent.ACTION_POINTER_2_UP) + && mSloppyGesture) { + // Set focus point to the remaining finger + int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK) + >> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0; + mFocusX = event.getX(id); + mFocusY = event.getY(id); } } else { // Transform gesture in progress - attempt to handle it diff --git a/core/java/android/webkit/DebugFlags.java b/core/java/android/webkit/DebugFlags.java index 8e25395..dca52f6 100644 --- a/core/java/android/webkit/DebugFlags.java +++ b/core/java/android/webkit/DebugFlags.java @@ -32,6 +32,8 @@ class DebugFlags { public static final boolean CALLBACK_PROXY = false; public static final boolean COOKIE_MANAGER = false; public static final boolean COOKIE_SYNC_MANAGER = false; + public static final boolean DRAG_TRACKER = false; + public static final String DRAG_TRACKER_LOGTAG = "skia"; public static final boolean FRAME_LOADER = false; public static final boolean J_WEB_CORE_JAVA_BRIDGE = false;// HIGHLY VERBOSE public static final boolean LOAD_LISTENER = false; diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 5b4ec60..ab1841e 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -200,6 +200,8 @@ public class WebView extends AbsoluteLayout implements ViewTreeObserver.OnGlobalFocusChangeListener, ViewGroup.OnHierarchyChangeListener { + // enable debug output for drag trackers + private static final boolean DEBUG_DRAG_TRACKER = false; // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing // the screen all-the-time. Good for profiling our drawing code static private final boolean AUTO_REDRAW_HACK = false; @@ -2796,16 +2798,7 @@ public class WebView extends AbsoluteLayout return super.drawChild(canvas, child, drawingTime); } - @Override - protected void onDraw(Canvas canvas) { - // if mNativeClass is 0, the WebView has been destroyed. Do nothing. - if (mNativeClass == 0) { - return; - } - int saveCount = canvas.save(); - if (mTitleBar != null) { - canvas.translate(0, (int) mTitleBar.getHeight()); - } + private void drawContent(Canvas canvas) { // Update the buttons in the picture, so when we draw the picture // to the screen, they are in the correct state. // Tell the native side if user is a) touching the screen, @@ -2818,6 +2811,21 @@ public class WebView extends AbsoluteLayout mTouchMode == TOUCH_SHORTPRESS_START_MODE || mTrackballDown || mGotCenterDown, false); drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing); + } + + @Override + protected void onDraw(Canvas canvas) { + // if mNativeClass is 0, the WebView has been destroyed. Do nothing. + if (mNativeClass == 0) { + return; + } + int saveCount = canvas.save(); + if (mTitleBar != null) { + canvas.translate(0, (int) mTitleBar.getHeight()); + } + if (mDragTrackerHandler == null || !mDragTrackerHandler.draw(canvas)) { + drawContent(canvas); + } canvas.restoreToCount(saveCount); // Now draw the shadow. @@ -3790,6 +3798,162 @@ public class WebView extends AbsoluteLayout } } + // if the page can scroll <= this value, we won't allow the drag tracker + // to have any effect. + private static final int MIN_SCROLL_AMOUNT_TO_DISABLE_DRAG_TRACKER = 4; + + private class DragTrackerHandler { + private final DragTracker mProxy; + private final float mStartY, mStartX; + private final float mMinDY, mMinDX; + private final float mMaxDY, mMaxDX; + private float mCurrStretchY, mCurrStretchX; + private int mSX, mSY; + + public DragTrackerHandler(float x, float y, DragTracker proxy) { + mProxy = proxy; + + int docBottom = computeVerticalScrollRange() + getTitleHeight(); + int viewTop = getScrollY(); + int viewBottom = viewTop + getHeight(); + + mStartY = y; + mMinDY = -viewTop; + mMaxDY = docBottom - viewBottom; + + if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { + Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, " dragtracker y= " + y + + " up/down= " + mMinDY + " " + mMaxDY); + } + + int docRight = computeHorizontalScrollRange(); + int viewLeft = getScrollX(); + int viewRight = viewLeft + getWidth(); + mStartX = x; + mMinDX = -viewLeft; + mMaxDX = docRight - viewRight; + + mProxy.onStartDrag(x, y); + + // ensure we buildBitmap at least once + mSX = -99999; + } + + private float computeStretch(float delta, float min, float max) { + float stretch = 0; + if (max - min > MIN_SCROLL_AMOUNT_TO_DISABLE_DRAG_TRACKER) { + if (delta < min) { + stretch = delta - min; + } else if (delta > max) { + stretch = delta - max; + } + } + return stretch; + } + + public void dragTo(float x, float y) { + float sy = computeStretch(mStartY - y, mMinDY, mMaxDY); + float sx = computeStretch(mStartX - x, mMinDX, mMaxDX); + + if (mCurrStretchX != sx || mCurrStretchY != sy) { + mCurrStretchX = sx; + mCurrStretchY = sy; + if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { + Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "---- stretch " + sx + + " " + sy); + } + if (mProxy.onStretchChange(sx, sy)) { + invalidate(); + } + } + } + + public void stopDrag() { + if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { + Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "----- stopDrag"); + } + mProxy.onStopDrag(); + } + + private int hiddenHeightOfTitleBar() { + return getTitleHeight() - getVisibleTitleHeight(); + } + + // need a way to know if 565 or 8888 is the right config for + // capturing the display and giving it to the drag proxy + private Bitmap.Config offscreenBitmapConfig() { + // hard code 565 for now + return Bitmap.Config.RGB_565; + } + + /* If the tracker draws, then this returns true, otherwise it will + return false, and draw nothing. + */ + public boolean draw(Canvas canvas) { + if (mCurrStretchX != 0 || mCurrStretchY != 0) { + int sx = getScrollX(); + int sy = getScrollY() - hiddenHeightOfTitleBar(); + + if (mSX != sx || mSY != sy) { + buildBitmap(sx, sy); + mSX = sx; + mSY = sy; + } + + int count = canvas.save(Canvas.MATRIX_SAVE_FLAG); + canvas.translate(sx, sy); + mProxy.onDraw(canvas); + canvas.restoreToCount(count); + return true; + } + if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { + Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, " -- draw false " + + mCurrStretchX + " " + mCurrStretchY); + } + return false; + } + + private void buildBitmap(int sx, int sy) { + int w = getWidth(); + int h = getViewHeight(); + Bitmap bm = Bitmap.createBitmap(w, h, offscreenBitmapConfig()); + Canvas canvas = new Canvas(bm); + canvas.translate(-sx, -sy); + drawContent(canvas); + + if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { + Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "--- buildBitmap " + sx + + " " + sy + " " + w + " " + h); + } + mProxy.onBitmapChange(bm); + } + } + + /** @hide */ + public static class DragTracker { + public void onStartDrag(float x, float y) {} + public boolean onStretchChange(float sx, float sy) { + // return true to have us inval the view + return false; + } + public void onStopDrag() {} + public void onBitmapChange(Bitmap bm) {} + public void onDraw(Canvas canvas) {} + } + + /** @hide */ + public DragTracker getDragTracker() { + return mDragTracker; + } + + /** @hide */ + public void setDragTracker(DragTracker tracker) { + mDragTracker = tracker; + } + + private DragTracker mDragTracker; + private DragTrackerHandler mDragTrackerHandler; + @Override public boolean onTouchEvent(MotionEvent ev) { if (mNativeClass == 0 || !isClickable() || !isLongClickable()) { @@ -3801,19 +3965,41 @@ public class WebView extends AbsoluteLayout + mTouchMode); } + int action; + float x, y; + long eventTime = ev.getEventTime(); + // FIXME: we may consider to give WebKit an option to handle multi-touch // events later. if (mSupportMultiTouch && mMinZoomScale < mMaxZoomScale && ev.getPointerCount() > 1) { - mLastTouchTime = ev.getEventTime(); - return mScaleDetector.onTouchEvent(ev); + mScaleDetector.onTouchEvent(ev); + if (mScaleDetector.isInProgress()) { + mLastTouchTime = eventTime; + return true; + } + x = mScaleDetector.getFocusX(); + y = mScaleDetector.getFocusY(); + action = ev.getAction() & MotionEvent.ACTION_MASK; + if (action == MotionEvent.ACTION_POINTER_DOWN) { + cancelTouch(); + action = MotionEvent.ACTION_DOWN; + } else if (action == MotionEvent.ACTION_POINTER_UP) { + // set mLastTouchX/Y to the remaining point + mLastTouchX = x; + mLastTouchY = y; + } else if (action == MotionEvent.ACTION_MOVE) { + // negative x or y indicate it is on the edge, skip it. + if (x < 0 || y < 0) { + return true; + } + } + } else { + action = ev.getAction(); + x = ev.getX(); + y = ev.getY(); } - int action = ev.getAction(); - float x = ev.getX(); - float y = ev.getY(); - long eventTime = ev.getEventTime(); - // Due to the touch screen edge effect, a touch closer to the edge // always snapped to the edge. As getViewWidth() can be different from // getWidth() due to the scrollbar, adjusting the point to match @@ -3888,6 +4074,10 @@ public class WebView extends AbsoluteLayout } // Remember where the motion event started startTouch(x, y, eventTime); + if (mDragTracker != null) { + mDragTrackerHandler = new DragTrackerHandler(x, y, + mDragTracker); + } break; } case MotionEvent.ACTION_MOVE: { @@ -4045,6 +4235,10 @@ public class WebView extends AbsoluteLayout } } + if (mDragTrackerHandler != null) { + mDragTrackerHandler.dragTo(x, y); + } + if (done) { // keep the scrollbar on the screen even there is no scroll awakenScrollBars(ViewConfiguration.getScrollDefaultDelay(), @@ -4056,6 +4250,10 @@ public class WebView extends AbsoluteLayout break; } case MotionEvent.ACTION_UP: { + if (mDragTrackerHandler != null) { + mDragTrackerHandler.stopDrag(); + mDragTrackerHandler = null; + } mLastTouchUpTime = eventTime; switch (mTouchMode) { case TOUCH_DOUBLE_TAP_MODE: // double tap @@ -4131,6 +4329,10 @@ public class WebView extends AbsoluteLayout break; } case MotionEvent.ACTION_CANCEL: { + if (mDragTrackerHandler != null) { + mDragTrackerHandler.stopDrag(); + mDragTrackerHandler = null; + } cancelTouch(); break; } diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index dc72008..7f526d1 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -27,6 +27,9 @@ #include "SkShader.h" #include "SkTemplates.h" +#include "SkBoundaryPatch.h" +#include "SkMeshUtils.h" + #define TIME_DRAWx static uint32_t get_thread_msec() { @@ -965,6 +968,42 @@ static JNINativeMethod gCanvasMethods[] = { {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches} }; +/////////////////////////////////////////////////////////////////////////////// + +static void BoundaryPatch_computeCubic(JNIEnv* env, jobject, jfloatArray jpts, + int texW, int texH, int rows, int cols, + jfloatArray jverts, jshortArray jidx) { + AutoJavaFloatArray ptsArray(env, jpts, 24); + + int vertCount = rows * cols; + AutoJavaFloatArray vertsArray(env, jverts, vertCount * 4); + SkPoint* verts = (SkPoint*)vertsArray.ptr(); + SkPoint* texs = verts + vertCount; + + int idxCount = (rows - 1) * (cols - 1) * 6; + AutoJavaShortArray idxArray(env, jidx, idxCount); + uint16_t* idx = (uint16_t*)idxArray.ptr(); // cast from int16_t* + + SkCubicBoundary cubic; + memcpy(cubic.fPts, ptsArray.ptr(), 12 * sizeof(SkPoint)); + + SkBoundaryPatch patch; + patch.setBoundary(&cubic); + // generate our verts + patch.evalPatch(verts, rows, cols); + + SkMeshIndices mesh; + // generate our texs and idx + mesh.init(texs, idx, texW, texH, rows, cols); +} + +static JNINativeMethod gBoundaryPatchMethods[] = { + {"nativeComputeCubicPatch", "([FIIII[F[S)V", + (void*)BoundaryPatch_computeCubic }, +}; + +/////////////////////////////////////////////////////////////////////////////// + #include <android_runtime/AndroidRuntime.h> #define REG(env, name, array) \ @@ -976,7 +1015,8 @@ int register_android_graphics_Canvas(JNIEnv* env) { int result; REG(env, "android/graphics/Canvas", gCanvasMethods); - + REG(env, "android/graphics/utils/BoundaryPatch", gBoundaryPatchMethods); + return result; } diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp index 238ece1..7c7bfeb 100644 --- a/core/jni/android/graphics/Typeface.cpp +++ b/core/jni/android/graphics/Typeface.cpp @@ -46,7 +46,7 @@ static SkTypeface* Typeface_createFromTypeface(JNIEnv* env, jobject, SkTypeface* } static void Typeface_unref(JNIEnv* env, jobject obj, SkTypeface* face) { - face->unref(); + SkSafeUnref(face); } static int Typeface_getStyle(JNIEnv* env, jobject obj, SkTypeface* face) { diff --git a/docs/html/guide/developing/debug-tasks.jd b/docs/html/guide/developing/debug-tasks.jd index 975f699..a980efc 100644 --- a/docs/html/guide/developing/debug-tasks.jd +++ b/docs/html/guide/developing/debug-tasks.jd @@ -80,13 +80,25 @@ href="#additionaldebugging">Debugging and Testing with Dev Tools</a> below.</dd> <h2 id="additionaldebugging">Debugging and Testing with Dev Tools</h2> -<p>With the Dev Tools application, you can turn on a number of settings that will -make it easier to test and debug your applications. The Dev Tools application is automatically -installed on all system images included with the SDK. The source code for the Dev Tools application -is also provided in the SDK samples so that you may build it and then install the application on any -development device.</p> +<p>With the Dev Tools application, you can enable a number of settings on your device that will +make it easier to test and debug your applications.</p> + +<p>The Dev Tools application is installed by default +on all system images included with the SDK, so you can use it with the Android Emulator. If you'd +like to install the Dev Tools application on a real development device, you can copy the +application from your emulator and then install it on your device using ADB. To copy the +application from a running emulator, execute: +</p> +<pre> +adb -e pull /system/app/Development.apk ./Development.apk +</pre> +<p>This copies the .apk file into the current directory. Then install it on your connected device +with:</p> +<pre> +adb -d install Development.apk +</pre> -<p>To get to the development settings page on the emulator, launch the Dev Tools application and +<p>To get started, launch the Dev Tools application and select Development Settings. This will open the Development Settings page with the following options (among others):</p> @@ -132,7 +144,7 @@ following options (among others):</p> can happen during debugging.</dd> </dl> -<p>These settings will be remembered across emulator restarts. </p> +<p>These settings will be remembered across emulator restarts.</p> <h2 id="DebuggingWebPages">Debugging Web Pages</h2> diff --git a/graphics/java/android/graphics/utils/BoundaryPatch.java b/graphics/java/android/graphics/utils/BoundaryPatch.java new file mode 100644 index 0000000..1cd5e13 --- /dev/null +++ b/graphics/java/android/graphics/utils/BoundaryPatch.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics.utils; + +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Shader; +import android.graphics.Xfermode; + +/** + * @hide + */ +public class BoundaryPatch { + private Paint mPaint; + private Bitmap mTexture; + private int mRows; + private int mCols; + private float[] mCubicPoints; + private boolean mDirty; + // these are the computed output of the native code + private float[] mVerts; + private short[] mIndices; + + public BoundaryPatch() { + mRows = mCols = 2; // default minimum + mCubicPoints = new float[24]; + mPaint = new Paint(); + mPaint.setDither(true); + mPaint.setFilterBitmap(true); + mDirty = true; + } + + /** + * Set the boundary to be 4 cubics. This takes a single array of floats, + * and picks up the 12 pairs starting at offset, and treats them as + * the x,y coordinates of the cubic control points. The points wrap around + * a patch, as follows. For documentation purposes, pts[i] will mean the + * x,y pair of floats, as if pts[] were an array of "points". + * + * Top: pts[0..3] + * Right: pts[3..6] + * Bottom: pts[6..9] + * Right: pts[9..11], pts[0] + * + * The coordinates are copied from the input array, so subsequent changes + * to pts[] will not be reflected in the boundary. + * + * @param pts The src array of x,y pairs for the boundary cubics + * @param offset The index into pts of the first pair + * @param rows The number of points across to approximate the boundary. + * Must be >= 2, though very large values may slow down drawing + * @param cols The number of points down to approximate the boundary. + * Must be >= 2, though very large values may slow down drawing + */ + public void setCubicBoundary(float[] pts, int offset, int rows, int cols) { + if (rows < 2 || cols < 2) { + throw new RuntimeException("rows and cols must be >= 2"); + } + System.arraycopy(pts, offset, mCubicPoints, 0, 24); + if (mRows != rows || mCols != cols) { + mRows = rows; + mCols = cols; + } + mDirty = true; + } + + /** + * Reference a bitmap texture to be mapped onto the patch. + */ + public void setTexture(Bitmap texture) { + if (mTexture != texture) { + if (mTexture == null || + mTexture.getWidth() != texture.getWidth() || + mTexture.getHeight() != texture.getHeight()) { + // need to recompute texture coordinates + mDirty = true; + } + mTexture = texture; + mPaint.setShader(new BitmapShader(texture, + Shader.TileMode.CLAMP, + Shader.TileMode.CLAMP)); + } + } + + /** + * Return the paint flags for the patch + */ + public int getPaintFlags() { + return mPaint.getFlags(); + } + + /** + * Set the paint flags for the patch + */ + public void setPaintFlags(int flags) { + mPaint.setFlags(flags); + } + + /** + * Set the xfermode for the patch + */ + public void setXfermode(Xfermode mode) { + mPaint.setXfermode(mode); + } + + /** + * Set the alpha for the patch + */ + public void setAlpha(int alpha) { + mPaint.setAlpha(alpha); + } + + /** + * Draw the patch onto the canvas. + * + * setCubicBoundary() and setTexture() must be called before drawing. + */ + public void draw(Canvas canvas) { + if (mDirty) { + buildCache(); + mDirty = false; + } + + // cut the count in half, since mVerts.length is really the length of + // the verts[] and tex[] arrays combined + // (tex[] are stored after verts[]) + int vertCount = mVerts.length >> 1; + canvas.drawVertices(Canvas.VertexMode.TRIANGLES, vertCount, + mVerts, 0, mVerts, vertCount, null, 0, + mIndices, 0, mIndices.length, + mPaint); + } + + private void buildCache() { + // we need mRows * mCols points, for verts and another set for textures + // so *2 for going from points -> floats, and *2 for verts and textures + int vertCount = mRows * mCols * 4; + if (mVerts == null || mVerts.length != vertCount) { + mVerts = new float[vertCount]; + } + + int indexCount = (mRows - 1) * (mCols - 1) * 6; + if (mIndices == null || mIndices.length != indexCount) { + mIndices = new short[indexCount]; + } + + nativeComputeCubicPatch(mCubicPoints, + mTexture.getWidth(), mTexture.getHeight(), + mRows, mCols, mVerts, mIndices); + } + + private static native + void nativeComputeCubicPatch(float[] cubicPoints, + int texW, int texH, int rows, int cols, + float[] verts, short[] indices); +} + diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 14c70bc..08eceac 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -454,6 +454,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { IBinder mBinder; int mPid; int mUid; + long mCreateTime; FeatureUser(int type, String feature, IBinder binder) { super(); @@ -462,6 +463,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { mBinder = binder; mPid = getCallingPid(); mUid = getCallingUid(); + mCreateTime = System.currentTimeMillis(); try { mBinder.linkToDeath(this, 0); @@ -476,15 +478,22 @@ public class ConnectivityService extends IConnectivityManager.Stub { public void binderDied() { Log.d(TAG, "ConnectivityService FeatureUser binderDied(" + - mNetworkType + ", " + mFeature + ", " + mBinder); + mNetworkType + ", " + mFeature + ", " + mBinder + "), created " + + (System.currentTimeMillis() - mCreateTime) + " mSec ago"); stopUsingNetworkFeature(this, false); } public void expire() { Log.d(TAG, "ConnectivityService FeatureUser expire(" + - mNetworkType + ", " + mFeature + ", " + mBinder); + mNetworkType + ", " + mFeature + ", " + mBinder +"), created " + + (System.currentTimeMillis() - mCreateTime) + " mSec ago"); stopUsingNetworkFeature(this, false); } + + public String toString() { + return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " + + (System.currentTimeMillis() - mCreateTime) + " mSec ago"; + } } // javadoc from interface @@ -596,6 +605,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { return stopUsingNetworkFeature(u, true); } else { // none found! + if (DBG) Log.d(TAG, "ignoring stopUsingNetworkFeature - not a live request"); return 1; } } @@ -640,6 +650,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (x.mUid == u.mUid && x.mPid == u.mPid && x.mNetworkType == u.mNetworkType && TextUtils.equals(x.mFeature, u.mFeature)) { + if (DBG) Log.d(TAG, "ignoring stopUsingNetworkFeature as dup is found"); return 1; } } @@ -1198,14 +1209,32 @@ public class ConnectivityService extends IConnectivityManager.Stub { } pw.println(); for (NetworkStateTracker nst : mNetTrackers) { - if (nst.getNetworkInfo().isConnected()) { - pw.println("Active network: " + nst.getNetworkInfo(). - getTypeName()); + if (nst != null) { + if (nst.getNetworkInfo().isConnected()) { + pw.println("Active network: " + nst.getNetworkInfo(). + getTypeName()); + } + pw.println(nst.getNetworkInfo()); + pw.println(nst); + pw.println(); + } + } + + pw.println("Network Requester Pids:"); + for (int net : mPriorityList) { + String pidString = net + ": "; + for (Object pid : mNetRequestersPids[net]) { + pidString = pidString + pid.toString() + ", "; } - pw.println(nst.getNetworkInfo()); - pw.println(nst); - pw.println(); + pw.println(pidString); } + pw.println(); + + pw.println("FeatureUsers:"); + for (Object requester : mFeatureUsers) { + pw.println(requester.toString()); + } + pw.println(); } // must be stateless - things change under us. diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index b29e769..3a08e4d 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -329,6 +329,17 @@ public class WifiService extends IWifiManager.Stub { return false; } + /** + * Multiple calls to unregisterReceiver() cause exception and a system crash. + * This can happen if a supplicant is lost (or firmware crash occurs) and user indicates + * disable wifi at the same time. + * Avoid doing a disable when the current Wifi state is UNKNOWN + * TODO: Handle driver load fail and supplicant lost as seperate states + */ + if (mWifiState == WIFI_STATE_UNKNOWN && !enable) { + return false; + } + setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid); if (enable) { |
