Merge "Fix failure to open AVRCP input device due to EPERM." into eclair
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 @@
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;
+ mSloppyGesture = true;
+ } else if (p0sloppy) {
mFocusX = event.getX(1);
mFocusY = event.getY(1);
mSloppyGesture = true;
@@ -211,12 +215,15 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
+ // 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 @@
+ 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 @@
}
// 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 @@
}
}
+ 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 @@
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 @@
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 @@
{"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 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 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 975f6998..a980efc 100644
--- a/docs/html/guide/developing/debug-tasks.jd
+++ b/docs/html/guide/developing/debug-tasks.jd
@@ -80,13 +80,25 @@
<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>To get to the development settings page on the emulator, launch the Dev Tools application and
+<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 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 @@
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 @@
IBinder mBinder;
int mPid;
int mUid;
+ long mCreateTime;
FeatureUser(int type, String feature, IBinder binder) {
super();
@@ -462,6 +463,7 @@
mBinder = binder;
mPid = getCallingPid();
mUid = getCallingUid();
+ mCreateTime = System.currentTimeMillis();
try {
mBinder.linkToDeath(this, 0);
@@ -476,15 +478,22 @@
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 @@
return stopUsingNetworkFeature(u, true);
} else {
// none found!
+ if (DBG) Log.d(TAG, "ignoring stopUsingNetworkFeature - not a live request");
return 1;
}
}
@@ -640,6 +650,7 @@
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 @@
}
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(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(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 @@
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) {