summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityThread.java15
-rw-r--r--core/java/android/app/Fragment.java27
-rw-r--r--core/java/android/app/FragmentManager.java12
-rw-r--r--core/java/android/app/LoadedApk.java5
-rw-r--r--core/java/android/content/AsyncTaskLoader.java2
-rw-r--r--core/java/android/content/ContentProvider.java2
-rw-r--r--core/java/android/inputmethodservice/IInputMethodSessionWrapper.java2
-rw-r--r--core/java/android/inputmethodservice/SoftInputWindow.java57
-rw-r--r--core/java/android/util/Base64DataException.java30
-rw-r--r--core/java/android/util/Base64InputStream.java2
-rw-r--r--core/java/android/util/Base64OutputStream.java2
-rw-r--r--core/java/android/util/LogWriter.java82
-rw-r--r--core/java/android/view/GLES20Canvas.java142
-rw-r--r--core/java/android/view/HardwareCanvas.java5
-rw-r--r--core/java/android/view/HardwareRenderer.java98
-rw-r--r--core/java/android/view/View.java56
-rw-r--r--core/java/android/view/ViewGroup.java18
-rw-r--r--core/java/android/view/ViewRoot.java15
-rw-r--r--core/java/android/widget/ListView.java2
19 files changed, 462 insertions, 112 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 511ddc1..960b943 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2385,7 +2385,9 @@ public final class ActivityThread {
performPauseActivity(token, finished, r.isPreHoneycomb());
// Make sure any pending writes are now committed.
- QueuedWork.waitToFinish();
+ if (r.isPreHoneycomb()) {
+ QueuedWork.waitToFinish();
+ }
// Tell the activity manager we have paused.
try {
@@ -2583,6 +2585,11 @@ public final class ActivityThread {
updateVisibility(r, show);
+ // Make sure any pending writes are now committed.
+ if (!r.isPreHoneycomb()) {
+ QueuedWork.waitToFinish();
+ }
+
// Tell activity manager we have been stopped.
try {
ActivityManagerNative.getDefault().activityStopped(
@@ -2647,6 +2654,12 @@ public final class ActivityThread {
}
r.stopped = true;
}
+
+ // Make sure any pending writes are now committed.
+ if (!r.isPreHoneycomb()) {
+ QueuedWork.waitToFinish();
+ }
+
// Tell activity manager we slept.
try {
ActivityManagerNative.getDefault().activitySlept(r.token);
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 3280b22..b3d111a 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -357,6 +357,9 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
// True if the fragment is in the list of added fragments.
boolean mAdded;
+ // If set this fragment is being removed from its activity.
+ boolean mRemoving;
+
// True if the fragment is in the resumed state.
boolean mResumed;
@@ -638,6 +641,9 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
* Return <code>getActivity().getResources()</code>.
*/
final public Resources getResources() {
+ if (mActivity == null) {
+ throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+ }
return mActivity.getResources();
}
@@ -689,7 +695,16 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
* Return true if the fragment is currently added to its activity.
*/
final public boolean isAdded() {
- return mActivity != null && mActivity.mFragments.mAdded.contains(this);
+ return mActivity != null && mAdded;
+ }
+
+ /**
+ * Return true if this fragment is currently being removed from its
+ * activity. This is <em>not</em> whether its activity is finishing, but
+ * rather whether it is in the process of being removed from its activity.
+ */
+ final public boolean isRemoving() {
+ return mRemoving;
}
/**
@@ -787,6 +802,9 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
if (mLoaderManager != null) {
return mLoaderManager;
}
+ if (mActivity == null) {
+ throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+ }
mCheckedForLoaderManager = true;
mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, true);
return mLoaderManager;
@@ -797,6 +815,9 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
* containing Activity.
*/
public void startActivity(Intent intent) {
+ if (mActivity == null) {
+ throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+ }
mActivity.startActivityFromFragment(this, intent, -1);
}
@@ -805,6 +826,9 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
* containing Activity.
*/
public void startActivityForResult(Intent intent, int requestCode) {
+ if (mActivity == null) {
+ throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+ }
mActivity.startActivityFromFragment(this, intent, requestCode);
}
@@ -1217,6 +1241,7 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
writer.print(" mWho="); writer.print(mWho);
writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
writer.print(prefix); writer.print("mAdded="); writer.print(mAdded);
+ writer.print(" mRemoving="); writer.print(mRemoving);
writer.print(" mResumed="); writer.print(mResumed);
writer.print(" mFromLayout="); writer.print(mFromLayout);
writer.print(" mInLayout="); writer.println(mInLayout);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index e729805..2c9c85b 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -28,6 +28,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.util.DebugUtils;
import android.util.Log;
+import android.util.LogWriter;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuInflater;
@@ -968,6 +970,7 @@ final class FragmentManagerImpl extends FragmentManager {
makeActive(fragment);
if (DEBUG) Log.v(TAG, "add: " + fragment);
fragment.mAdded = true;
+ fragment.mRemoving = false;
if (fragment.mHasMenu) {
mNeedMenuInvalidate = true;
}
@@ -984,6 +987,7 @@ final class FragmentManagerImpl extends FragmentManager {
mNeedMenuInvalidate = true;
}
fragment.mAdded = false;
+ fragment.mRemoving = true;
moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
transition, transitionStyle);
if (inactive) {
@@ -1376,6 +1380,14 @@ final class FragmentManagerImpl extends FragmentManager {
}
if (f.mTarget != null) {
+ if (f.mTarget.mIndex < 0) {
+ String msg = "Failure saving state: " + f
+ + " has target not in fragment manager: " + f.mTarget;
+ Slog.e(TAG, msg);
+ dump(" ", null, new PrintWriter(new LogWriter(
+ Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
+ throw new IllegalStateException(msg);
+ }
if (fs.mSavedFragmentState == null) {
fs.mSavedFragmentState = new Bundle();
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 60213f8..c406524 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -567,6 +567,7 @@ final class LoadedApk {
} else {
rd.validate(context, handler);
}
+ rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}
@@ -596,6 +597,7 @@ final class LoadedApk {
rd.setUnregisterLocation(ex);
holder.put(r, rd);
}
+ rd.mForgotten = true;
return rd.getIIntentReceiver();
}
}
@@ -666,6 +668,7 @@ final class LoadedApk {
final boolean mRegistered;
final IntentReceiverLeaked mLocation;
RuntimeException mUnregisterLocation;
+ boolean mForgotten;
final class Args extends BroadcastReceiver.PendingResult implements Runnable {
private Intent mCurIntent;
@@ -696,7 +699,7 @@ final class LoadedApk {
final Intent intent = mCurIntent;
mCurIntent = null;
- if (receiver == null || !mRegistered) {
+ if (receiver == null || mForgotten) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing null broadcast to " + mReceiver);
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index 3d6182b..a7dd5fb 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -195,7 +195,7 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> {
}
}
if (DEBUG) Slog.v(TAG, "Executing: " + mTask);
- mTask.execute((Void[]) null);
+ mTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
}
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 5467a30..1764e11 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -899,7 +899,7 @@ public abstract class ContentProvider implements ComponentCallbacks {
return null;
}
};
- task.execute((Object[])null);
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null);
return fds[0];
} catch (IOException e) {
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index 01fc010..df8cf9a 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -76,6 +76,8 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
}
public void executeMessage(Message msg) {
+ if (mInputMethodSession == null) return;
+
switch (msg.what) {
case DO_FINISH_INPUT:
mInputMethodSession.finishInput();
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
index 6a54846..343242e 100644
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ b/core/java/android/inputmethodservice/SoftInputWindow.java
@@ -19,11 +19,16 @@ package android.inputmethodservice;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
import android.os.IBinder;
import android.view.Gravity;
import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
import android.view.WindowManager;
+import java.lang.Math;
+
/**
* A SoftInputWindow is a Dialog that is intended to be used for a top-level input
* method window. It will be displayed along the edge of the screen, moving
@@ -32,6 +37,7 @@ import android.view.WindowManager;
*/
class SoftInputWindow extends Dialog {
final KeyEvent.DispatcherState mDispatcherState;
+ private final Rect mBounds = new Rect();
public void setToken(IBinder token) {
WindowManager.LayoutParams lp = getWindow().getAttributes();
@@ -64,6 +70,13 @@ class SoftInputWindow extends Dialog {
mDispatcherState.reset();
}
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ getWindow().getDecorView().getHitRect(mBounds);
+ final MotionEvent event = clipMotionEvent(ev, mBounds);
+ return super.dispatchTouchEvent(event);
+ }
+
/**
* Get the size of the DockWindow.
*
@@ -150,4 +163,48 @@ class SoftInputWindow extends Dialog {
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
+
+ private static MotionEvent clipMotionEvent(MotionEvent me, Rect bounds) {
+ final int pointerCount = me.getPointerCount();
+ boolean shouldClip = false;
+ for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
+ final int x = (int)me.getX(pointerIndex);
+ final int y = (int)me.getY(pointerIndex);
+ if (!bounds.contains(x, y)) {
+ shouldClip = true;
+ break;
+ }
+ }
+ if (!shouldClip)
+ return me;
+
+ if (pointerCount == 1) {
+ final int x = (int)me.getX();
+ final int y = (int)me.getY();
+ me.setLocation(
+ Math.max(bounds.left, Math.min(x, bounds.right - 1)),
+ Math.max(bounds.top, Math.min(y, bounds.bottom - 1)));
+ return me;
+ }
+
+ final int[] pointerIds = new int[pointerCount];
+ final MotionEvent.PointerCoords[] pointerCoords =
+ new MotionEvent.PointerCoords[pointerCount];
+ for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
+ pointerIds[pointerIndex] = me.getPointerId(pointerIndex);
+ final MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
+ me.getPointerCoords(pointerIndex, coords);
+ pointerCoords[pointerIndex] = coords;
+ final int x = (int)coords.x;
+ final int y = (int)coords.y;
+ if (!bounds.contains(x, y)) {
+ coords.x = Math.max(bounds.left, Math.min(x, bounds.right - 1));
+ coords.y = Math.max(bounds.top, Math.min(y, bounds.bottom - 1));
+ }
+ }
+ return MotionEvent.obtain(
+ me.getDownTime(), me.getEventTime(), me.getAction(), pointerCount, pointerIds,
+ pointerCoords, me.getMetaState(), me.getXPrecision(), me.getYPrecision(),
+ me.getDeviceId(), me.getEdgeFlags(), me.getSource(), me.getFlags());
+ }
}
diff --git a/core/java/android/util/Base64DataException.java b/core/java/android/util/Base64DataException.java
new file mode 100644
index 0000000..de12ee1
--- /dev/null
+++ b/core/java/android/util/Base64DataException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+package android.util;
+
+import java.io.IOException;
+
+/**
+ * This exception is thrown by {@link Base64InputStream} or {@link Base64OutputStream}
+ * when an error is detected in the data being decoded. This allows problems with the base64 data
+ * to be disambiguated from errors in the underlying streams (e.g. actual connection errors.)
+ */
+public class Base64DataException extends IOException {
+ public Base64DataException(String detailMessage) {
+ super(detailMessage);
+ }
+}
diff --git a/core/java/android/util/Base64InputStream.java b/core/java/android/util/Base64InputStream.java
index e9dac24..9eba5b5 100644
--- a/core/java/android/util/Base64InputStream.java
+++ b/core/java/android/util/Base64InputStream.java
@@ -145,7 +145,7 @@ public class Base64InputStream extends FilterInputStream {
success = coder.process(inputBuffer, 0, bytesRead, false);
}
if (!success) {
- throw new IOException("bad base-64");
+ throw new Base64DataException("bad base-64");
}
outputEnd = coder.op;
outputStart = 0;
diff --git a/core/java/android/util/Base64OutputStream.java b/core/java/android/util/Base64OutputStream.java
index 30d632d..4535d1c 100644
--- a/core/java/android/util/Base64OutputStream.java
+++ b/core/java/android/util/Base64OutputStream.java
@@ -136,7 +136,7 @@ public class Base64OutputStream extends FilterOutputStream {
private void internalWrite(byte[] b, int off, int len, boolean finish) throws IOException {
coder.output = embiggen(coder.output, coder.maxOutputSize(len));
if (!coder.process(b, off, len, finish)) {
- throw new IOException("bad base-64");
+ throw new Base64DataException("bad base-64");
}
out.write(coder.output, 0, coder.op);
}
diff --git a/core/java/android/util/LogWriter.java b/core/java/android/util/LogWriter.java
new file mode 100644
index 0000000..ce30631
--- /dev/null
+++ b/core/java/android/util/LogWriter.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package android.util;
+
+import java.io.Writer;
+
+/** @hide */
+public class LogWriter extends Writer {
+ private final int mPriority;
+ private final String mTag;
+ private final int mBuffer;
+ private StringBuilder mBuilder = new StringBuilder(128);
+
+ /**
+ * Create a new Writer that sends to the log with the given priority
+ * and tag.
+ *
+ * @param priority The desired log priority:
+ * {@link android.util.Log#VERBOSE Log.VERBOSE},
+ * {@link android.util.Log#DEBUG Log.DEBUG},
+ * {@link android.util.Log#INFO Log.INFO},
+ * {@link android.util.Log#WARN Log.WARN}, or
+ * {@link android.util.Log#ERROR Log.ERROR}.
+ * @param tag A string tag to associate with each printed log statement.
+ */
+ public LogWriter(int priority, String tag) {
+ mPriority = priority;
+ mTag = tag;
+ mBuffer = Log.LOG_ID_MAIN;
+ }
+
+ /**
+ * @hide
+ * Same as above, but buffer is one of the LOG_ID_ constants from android.util.Log.
+ */
+ public LogWriter(int priority, String tag, int buffer) {
+ mPriority = priority;
+ mTag = tag;
+ mBuffer = buffer;
+ }
+
+ @Override public void close() {
+ flushBuilder();
+ }
+
+ @Override public void flush() {
+ flushBuilder();
+ }
+
+ @Override public void write(char[] buf, int offset, int count) {
+ for(int i = 0; i < count; i++) {
+ char c = buf[offset + i];
+ if ( c == '\n') {
+ flushBuilder();
+ }
+ else {
+ mBuilder.append(c);
+ }
+ }
+ }
+
+ private void flushBuilder() {
+ if (mBuilder.length() > 0) {
+ Log.println_native(mBuffer, mPriority, mTag, mBuilder.toString());
+ mBuilder.delete(0, mBuilder.length());
+ }
+ }
+}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index dce1a6c..dac3135 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -192,21 +192,36 @@ class GLES20Canvas extends HardwareCanvas {
nSetViewport(mRenderer, width, height);
}
- private native void nSetViewport(int renderer, int width, int height);
+ private static native void nSetViewport(int renderer, int width, int height);
+ /**
+ * @hide
+ */
+ public static boolean preserveBackBuffer() {
+ return nPreserveBackBuffer();
+ }
+
+ private static native boolean nPreserveBackBuffer();
+
@Override
- void onPreDraw() {
- nPrepare(mRenderer, mOpaque);
+ void onPreDraw(Rect dirty) {
+ if (dirty != null) {
+ nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom, mOpaque);
+ } else {
+ nPrepare(mRenderer, mOpaque);
+ }
}
- private native void nPrepare(int renderer, boolean opaque);
+ private static native void nPrepare(int renderer, boolean opaque);
+ private static native void nPrepareDirty(int renderer, int left, int top, int right, int bottom,
+ boolean opaque);
@Override
void onPostDraw() {
nFinish(mRenderer);
}
- private native void nFinish(int renderer);
+ private static native void nFinish(int renderer);
@Override
public boolean acquireContext() {
@@ -217,14 +232,14 @@ class GLES20Canvas extends HardwareCanvas {
return mContextLocked;
}
- private native void nAcquireContext(int renderer);
+ private static native void nAcquireContext(int renderer);
@Override
public boolean callDrawGLFunction(int drawGLFunction) {
return nCallDrawGLFunction(mRenderer, drawGLFunction);
}
- private native boolean nCallDrawGLFunction(int renderer, int drawGLFunction);
+ private static native boolean nCallDrawGLFunction(int renderer, int drawGLFunction);
@Override
public void releaseContext() {
@@ -234,7 +249,7 @@ class GLES20Canvas extends HardwareCanvas {
}
}
- private native void nReleaseContext(int renderer);
+ private static native void nReleaseContext(int renderer);
///////////////////////////////////////////////////////////////////////////
// Display list
@@ -244,7 +259,7 @@ class GLES20Canvas extends HardwareCanvas {
return nGetDisplayList(mRenderer);
}
- private native int nGetDisplayList(int renderer);
+ private static native int nGetDisplayList(int renderer);
static void destroyDisplayList(int displayList) {
nDestroyDisplayList(displayList);
@@ -257,7 +272,7 @@ class GLES20Canvas extends HardwareCanvas {
return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
}
- private native boolean nDrawDisplayList(int renderer, int displayList);
+ private static native boolean nDrawDisplayList(int renderer, int displayList);
///////////////////////////////////////////////////////////////////////////
// Hardware layer
@@ -271,7 +286,7 @@ class GLES20Canvas extends HardwareCanvas {
if (hasColorFilter) nResetModifiers(mRenderer);
}
- private native void nDrawLayer(int renderer, int layer, float x, float y, int paint);
+ private static native void nDrawLayer(int renderer, int layer, float x, float y, int paint);
void interrupt() {
nInterrupt(mRenderer);
@@ -281,8 +296,8 @@ class GLES20Canvas extends HardwareCanvas {
nResume(mRenderer);
}
- private native void nInterrupt(int renderer);
- private native void nResume(int renderer);
+ private static native void nInterrupt(int renderer);
+ private static native void nResume(int renderer);
///////////////////////////////////////////////////////////////////////////
// Clipping
@@ -303,7 +318,7 @@ class GLES20Canvas extends HardwareCanvas {
return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
}
- private native boolean nClipRect(int renderer, float left, float top,
+ private static native boolean nClipRect(int renderer, float left, float top,
float right, float bottom, int op);
@Override
@@ -316,7 +331,8 @@ class GLES20Canvas extends HardwareCanvas {
return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
}
- private native boolean nClipRect(int renderer, int left, int top, int right, int bottom, int op);
+ private static native boolean nClipRect(int renderer, int left, int top, int right, int bottom,
+ int op);
@Override
public boolean clipRect(Rect rect) {
@@ -355,14 +371,14 @@ class GLES20Canvas extends HardwareCanvas {
return nGetClipBounds(mRenderer, bounds);
}
- private native boolean nGetClipBounds(int renderer, Rect bounds);
+ private static native boolean nGetClipBounds(int renderer, Rect bounds);
@Override
public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
return nQuickReject(mRenderer, left, top, right, bottom, type.nativeInt);
}
- private native boolean nQuickReject(int renderer, float left, float top,
+ private static native boolean nQuickReject(int renderer, float left, float top,
float right, float bottom, int edge);
@Override
@@ -384,56 +400,56 @@ class GLES20Canvas extends HardwareCanvas {
if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
}
- private native void nTranslate(int renderer, float dx, float dy);
+ private static native void nTranslate(int renderer, float dx, float dy);
@Override
public void skew(float sx, float sy) {
nSkew(mRenderer, sx, sy);
}
- private native void nSkew(int renderer, float sx, float sy);
+ private static native void nSkew(int renderer, float sx, float sy);
@Override
public void rotate(float degrees) {
nRotate(mRenderer, degrees);
}
- private native void nRotate(int renderer, float degrees);
+ private static native void nRotate(int renderer, float degrees);
@Override
public void scale(float sx, float sy) {
nScale(mRenderer, sx, sy);
}
- private native void nScale(int renderer, float sx, float sy);
+ private static native void nScale(int renderer, float sx, float sy);
@Override
public void setMatrix(Matrix matrix) {
nSetMatrix(mRenderer, matrix.native_instance);
}
- private native void nSetMatrix(int renderer, int matrix);
+ private static native void nSetMatrix(int renderer, int matrix);
@Override
public int getNativeMatrix() {
return nGetMatrix(mRenderer);
}
- private native int nGetMatrix(int renderer);
+ private static native int nGetMatrix(int renderer);
@Override
public void getMatrix(Matrix matrix) {
nGetMatrix(mRenderer, matrix.native_instance);
}
- private native void nGetMatrix(int renderer, int matrix);
+ private static native void nGetMatrix(int renderer, int matrix);
@Override
public void concat(Matrix matrix) {
nConcatMatrix(mRenderer, matrix.native_instance);
}
- private native void nConcatMatrix(int renderer, int matrix);
+ private static native void nConcatMatrix(int renderer, int matrix);
///////////////////////////////////////////////////////////////////////////
// State management
@@ -449,7 +465,7 @@ class GLES20Canvas extends HardwareCanvas {
return nSave(mRenderer, saveFlags);
}
- private native int nSave(int renderer, int flags);
+ private static native int nSave(int renderer, int flags);
@Override
public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
@@ -469,8 +485,8 @@ class GLES20Canvas extends HardwareCanvas {
return save(saveFlags);
}
- private native int nSaveLayer(int renderer, float left, float top, float right, float bottom,
- int paint, int saveFlags);
+ private static native int nSaveLayer(int renderer, float left, float top,
+ float right, float bottom, int paint, int saveFlags);
@Override
public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
@@ -487,7 +503,7 @@ class GLES20Canvas extends HardwareCanvas {
return save(saveFlags);
}
- private native int nSaveLayerAlpha(int renderer, float left, float top, float right,
+ private static native int nSaveLayerAlpha(int renderer, float left, float top, float right,
float bottom, int alpha, int saveFlags);
@Override
@@ -495,21 +511,21 @@ class GLES20Canvas extends HardwareCanvas {
nRestore(mRenderer);
}
- private native void nRestore(int renderer);
+ private static native void nRestore(int renderer);
@Override
public void restoreToCount(int saveCount) {
nRestoreToCount(mRenderer, saveCount);
}
- private native void nRestoreToCount(int renderer, int saveCount);
+ private static native void nRestoreToCount(int renderer, int saveCount);
@Override
public int getSaveCount() {
return nGetSaveCount(mRenderer);
}
- private native int nGetSaveCount(int renderer);
+ private static native int nGetSaveCount(int renderer);
///////////////////////////////////////////////////////////////////////////
// Filtering
@@ -538,8 +554,9 @@ class GLES20Canvas extends HardwareCanvas {
if (hasModifier) nResetModifiers(mRenderer);
}
- private native void nDrawArc(int renderer, float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, boolean useCenter, int paint);
+ private static native void nDrawArc(int renderer, float left, float top,
+ float right, float bottom, float startAngle, float sweepAngle,
+ boolean useCenter, int paint);
@Override
public void drawARGB(int a, int r, int g, int b) {
@@ -556,7 +573,7 @@ class GLES20Canvas extends HardwareCanvas {
if (hasColorFilter) nResetModifiers(mRenderer);
}
- private native void nDrawPatch(int renderer, int bitmap, byte[] buffer, byte[] chunks,
+ private static native void nDrawPatch(int renderer, int bitmap, byte[] buffer, byte[] chunks,
float left, float top, float right, float bottom, int paint);
@Override
@@ -568,7 +585,7 @@ class GLES20Canvas extends HardwareCanvas {
if (hasColorFilter) nResetModifiers(mRenderer);
}
- private native void nDrawBitmap(
+ private static native void nDrawBitmap(
int renderer, int bitmap, byte[] buffer, float left, float top, int paint);
@Override
@@ -581,7 +598,8 @@ class GLES20Canvas extends HardwareCanvas {
if (hasColorFilter) nResetModifiers(mRenderer);
}
- private native void nDrawBitmap(int renderer, int bitmap, byte[] buff, int matrix, int paint);
+ private static native void nDrawBitmap(int renderer, int bitmap, byte[] buff,
+ int matrix, int paint);
@Override
public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
@@ -616,7 +634,7 @@ class GLES20Canvas extends HardwareCanvas {
if (hasColorFilter) nResetModifiers(mRenderer);
}
- private native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
+ private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float left, float top, float right, float bottom, int paint);
@@ -665,7 +683,7 @@ class GLES20Canvas extends HardwareCanvas {
if (hasColorFilter) nResetModifiers(mRenderer);
}
- private native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer,
+ private static native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer,
int meshWidth, int meshHeight, float[] verts, int vertOffset,
int[] colors, int colorOffset, int paint);
@@ -676,7 +694,8 @@ class GLES20Canvas extends HardwareCanvas {
if (hasModifier) nResetModifiers(mRenderer);
}
- private native void nDrawCircle(int renderer, float cx, float cy, float radius, int paint);
+ private static native void nDrawCircle(int renderer, float cx, float cy,
+ float radius, int paint);
@Override
public void drawColor(int color) {
@@ -688,7 +707,7 @@ class GLES20Canvas extends HardwareCanvas {
nDrawColor(mRenderer, color, mode.nativeInt);
}
- private native void nDrawColor(int renderer, int color, int mode);
+ private static native void nDrawColor(int renderer, int color, int mode);
@Override
public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
@@ -709,7 +728,8 @@ class GLES20Canvas extends HardwareCanvas {
if (hasModifier) nResetModifiers(mRenderer);
}
- private native void nDrawLines(int renderer, float[] points, int offset, int count, int paint);
+ private static native void nDrawLines(int renderer, float[] points,
+ int offset, int count, int paint);
@Override
public void drawLines(float[] pts, Paint paint) {
@@ -723,8 +743,8 @@ class GLES20Canvas extends HardwareCanvas {
if (hasModifier) nResetModifiers(mRenderer);
}
- private native void nDrawOval(int renderer, float left, float top, float right, float bottom,
- int paint);
+ private static native void nDrawOval(int renderer, float left, float top,
+ float right, float bottom, int paint);
@Override
public void drawPaint(Paint paint) {
@@ -746,8 +766,8 @@ class GLES20Canvas extends HardwareCanvas {
if (hasModifier) nResetModifiers(mRenderer);
}
- private native void nDrawPath(int renderer, int path, int paint);
- private native void nDrawRects(int renderer, int region, int paint);
+ private static native void nDrawPath(int renderer, int path, int paint);
+ private static native void nDrawRects(int renderer, int region, int paint);
@Override
public void drawPicture(Picture picture) {
@@ -798,8 +818,8 @@ class GLES20Canvas extends HardwareCanvas {
if (hasModifier) nResetModifiers(mRenderer);
}
- private native void nDrawRect(int renderer, float left, float top, float right, float bottom,
- int paint);
+ private static native void nDrawRect(int renderer, float left, float top,
+ float right, float bottom, int paint);
@Override
public void drawRect(Rect r, Paint paint) {
@@ -824,7 +844,7 @@ class GLES20Canvas extends HardwareCanvas {
if (hasModifier) nResetModifiers(mRenderer);
}
- private native void nDrawRoundRect(int renderer, float left, float top,
+ private static native void nDrawRoundRect(int renderer, float left, float top,
float right, float bottom, float rx, float y, int paint);
@Override
@@ -841,8 +861,8 @@ class GLES20Canvas extends HardwareCanvas {
}
}
- private native void nDrawText(int renderer, char[] text, int index, int count, float x, float y,
- int bidiFlags, int paint);
+ private static native void nDrawText(int renderer, char[] text, int index, int count,
+ float x, float y, int bidiFlags, int paint);
@Override
public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
@@ -858,7 +878,8 @@ class GLES20Canvas extends HardwareCanvas {
} else {
char[] buf = TemporaryBuffer.obtain(end - start);
TextUtils.getChars(text, start, end, buf, 0);
- nDrawText(mRenderer, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint);
+ nDrawText(mRenderer, buf, 0, end - start, x, y,
+ paint.mBidiFlags, paint.mNativePaint);
TemporaryBuffer.recycle(buf);
}
} finally {
@@ -880,8 +901,8 @@ class GLES20Canvas extends HardwareCanvas {
}
}
- private native void nDrawText(int renderer, String text, int start, int end, float x, float y,
- int bidiFlags, int paint);
+ private static native void nDrawText(int renderer, String text, int start, int end,
+ float x, float y, int bidiFlags, int paint);
@Override
public void drawText(String text, float x, float y, Paint paint) {
@@ -924,7 +945,7 @@ class GLES20Canvas extends HardwareCanvas {
}
}
- private native void nDrawTextRun(int renderer, char[] text, int index, int count,
+ private static native void nDrawTextRun(int renderer, char[] text, int index, int count,
int contextIndex, int contextCount, float x, float y, int dir, int nativePaint);
@Override
@@ -958,7 +979,7 @@ class GLES20Canvas extends HardwareCanvas {
}
}
- private native void nDrawTextRun(int renderer, String text, int start, int end,
+ private static native void nDrawTextRun(int renderer, String text, int start, int end,
int contextStart, int contextEnd, float x, float y, int flags, int nativePaint);
@Override
@@ -1001,9 +1022,10 @@ class GLES20Canvas extends HardwareCanvas {
return false;
}
- private native void nSetupShader(int renderer, int shader);
- private native void nSetupColorFilter(int renderer, int colorFilter);
- private native void nSetupShadow(int renderer, float radius, float dx, float dy, int color);
+ private static native void nSetupShader(int renderer, int shader);
+ private static native void nSetupColorFilter(int renderer, int colorFilter);
+ private static native void nSetupShadow(int renderer, float radius,
+ float dx, float dy, int color);
- private native void nResetModifiers(int renderer);
+ private static native void nResetModifiers(int renderer);
}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index a4d36b7..e6fecc8 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -19,6 +19,7 @@ package android.view;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.Rect;
/**
* Hardware accelerated canvas.
@@ -38,8 +39,10 @@ public abstract class HardwareCanvas extends Canvas {
/**
* Invoked before any drawing operation is performed in this canvas.
+ *
+ * @param dirty The dirty rectangle to update, can be null.
*/
- abstract void onPreDraw();
+ abstract void onPreDraw(Rect dirty);
/**
* Invoked after all drawing operation have been performed.
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index c82184a..48f40c3 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -18,6 +18,8 @@
package android.view;
import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
import android.os.SystemClock;
import android.util.EventLog;
import android.util.Log;
@@ -39,6 +41,16 @@ public abstract class HardwareRenderer {
static final String LOG_TAG = "HardwareRenderer";
/**
+ * Turn on to only refresh the parts of the screen that need updating.
+ */
+ public static final boolean RENDER_DIRTY_REGIONS = true;
+
+ /**
+ * Turn on to draw dirty regions every other frame.
+ */
+ private static final boolean DEBUG_DIRTY_REGION = false;
+
+ /**
* A process can set this flag to false to prevent the use of hardware
* rendering.
*
@@ -108,11 +120,14 @@ public abstract class HardwareRenderer {
/**
* Draws the specified view.
- *
+ *
* @param view The view to draw.
* @param attachInfo AttachInfo tied to the specified view.
+ * @param callbacks Callbacks invoked when drawing happens.
+ * @param dirty The dirty rectangle to update, can be null.
*/
- abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks);
+ abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
+ Rect dirty);
/**
* Creates a new display list that can be used to record batches of
@@ -214,7 +229,13 @@ public abstract class HardwareRenderer {
@SuppressWarnings({"deprecation"})
static abstract class GlRenderer extends HardwareRenderer {
private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ private static final int EGL_SURFACE_TYPE = 0x3033;
+ private static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
+ private static final int SURFACE_STATE_ERROR = 0;
+ private static final int SURFACE_STATE_SUCCESS = 1;
+ private static final int SURFACE_STATE_UPDATED = 2;
+
static EGLContext sEglContext;
static EGL10 sEgl;
static EGLDisplay sEglDisplay;
@@ -226,6 +247,9 @@ public abstract class HardwareRenderer {
GL mGl;
HardwareCanvas mCanvas;
+ int mFrameCount;
+ Paint mDebugPaint;
+
final int mGlVersion;
final boolean mTranslucent;
@@ -412,7 +436,7 @@ public abstract class HardwareRenderer {
if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
int error = sEgl.eglGetError();
if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
- Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
+ Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
return null;
}
throw new RuntimeException("createWindowSurface failed "
@@ -427,6 +451,12 @@ public abstract class HardwareRenderer {
throw new RuntimeException("eglMakeCurrent failed "
+ getEGLErrorString(sEgl.eglGetError()));
}
+
+ if (RENDER_DIRTY_REGIONS) {
+ if (!GLES20Canvas.preserveBackBuffer()) {
+ Log.w(LOG_TAG, "Backbuffer cannot be preserved");
+ }
+ }
return sEglContext.getGL();
}
@@ -471,12 +501,12 @@ public abstract class HardwareRenderer {
void setup(int width, int height) {
mCanvas.setViewport(width, height);
}
-
+
boolean canDraw() {
return mGl != null && mCanvas != null;
}
- void onPreDraw() {
+ void onPreDraw(Rect dirty) {
}
void onPostDraw() {
@@ -492,8 +522,14 @@ public abstract class HardwareRenderer {
}
@Override
- void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
+ void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
+ Rect dirty) {
if (canDraw()) {
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
+ dirty = null;
+ }
+
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
attachInfo.mIgnoreDirtyState = true;
view.mPrivateFlags |= View.DRAWN;
@@ -503,11 +539,18 @@ public abstract class HardwareRenderer {
startTime = SystemClock.elapsedRealtime();
}
- if (checkCurrent()) {
- onPreDraw();
+ final int surfaceState = checkCurrent();
+ if (surfaceState != SURFACE_STATE_ERROR) {
+ // We had to change the current surface and/or context, redraw everything
+ if (surfaceState == SURFACE_STATE_UPDATED) {
+ dirty = null;
+ }
+
+ onPreDraw(dirty);
HardwareCanvas canvas = mCanvas;
attachInfo.mHardwareCanvas = canvas;
+
int saveCount = canvas.save();
callbacks.onHardwarePreDraw(canvas);
@@ -515,6 +558,7 @@ public abstract class HardwareRenderer {
view.mRecreateDisplayList =
(view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED;
view.mPrivateFlags &= ~View.INVALIDATED;
+
DisplayList displayList = view.getDisplayList();
if (displayList != null) {
if (canvas.drawDisplayList(displayList)) {
@@ -524,6 +568,16 @@ public abstract class HardwareRenderer {
// Shouldn't reach here
view.draw(canvas);
}
+
+ if (DEBUG_DIRTY_REGION) {
+ if (mDebugPaint == null) {
+ mDebugPaint = new Paint();
+ mDebugPaint.setColor(0x7fff0000);
+ }
+ if (dirty != null && (mFrameCount++ & 1) == 0) {
+ canvas.drawRect(dirty, mDebugPaint);
+ }
+ }
} finally {
callbacks.onHardwarePostDraw(canvas);
canvas.restoreToCount(saveCount);
@@ -543,8 +597,8 @@ public abstract class HardwareRenderer {
}
}
}
-
- private boolean checkCurrent() {
+
+ private int checkCurrent() {
// TODO: Don't check the current context when we have one per UI thread
// TODO: Use a threadlocal flag to know whether the surface has changed
if (sEgl.eglGetCurrentContext() != sEglContext ||
@@ -553,10 +607,12 @@ public abstract class HardwareRenderer {
fallback(true);
Log.e(LOG_TAG, "eglMakeCurrent failed " +
getEGLErrorString(sEgl.eglGetError()));
- return false;
+ return SURFACE_STATE_ERROR;
+ } else {
+ return SURFACE_STATE_UPDATED;
}
}
- return true;
+ return SURFACE_STATE_SUCCESS;
}
static abstract class EglConfigChooser {
@@ -629,6 +685,7 @@ public abstract class HardwareRenderer {
ComponentSizeChooser(int glVersion, int redSize, int greenSize, int blueSize,
int alphaSize, int depthSize, int stencilSize) {
+ //noinspection PointlessBitwiseExpression
super(glVersion, new int[] {
EGL10.EGL_RED_SIZE, redSize,
EGL10.EGL_GREEN_SIZE, greenSize,
@@ -636,6 +693,8 @@ public abstract class HardwareRenderer {
EGL10.EGL_ALPHA_SIZE, alphaSize,
EGL10.EGL_DEPTH_SIZE, depthSize,
EGL10.EGL_STENCIL_SIZE, stencilSize,
+ EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT |
+ (RENDER_DIRTY_REGIONS ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
EGL10.EGL_NONE });
mValue = new int[1];
mRedSize = redSize;
@@ -656,7 +715,16 @@ public abstract class HardwareRenderer {
int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);
int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);
int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);
- if (r >= mRedSize && g >= mGreenSize && b >= mBlueSize && a >= mAlphaSize) {
+ boolean backBuffer;
+ if (RENDER_DIRTY_REGIONS) {
+ int surfaceType = findConfigAttrib(egl, display, config,
+ EGL_SURFACE_TYPE, 0);
+ backBuffer = (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) != 0;
+ } else {
+ backBuffer = true;
+ }
+ if (r >= mRedSize && g >= mGreenSize && b >= mBlueSize && a >= mAlphaSize
+ && backBuffer) {
return config;
}
}
@@ -696,8 +764,8 @@ public abstract class HardwareRenderer {
}
@Override
- void onPreDraw() {
- mGlCanvas.onPreDraw();
+ void onPreDraw(Rect dirty) {
+ mGlCanvas.onPreDraw(dirty);
}
@Override
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index aa69aea..65d2e11 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6730,11 +6730,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mPrivateFlags |= INVALIDATED;
final ViewParent p = mParent;
final AttachInfo ai = mAttachInfo;
- if (p != null && ai != null && ai.mHardwareAccelerated) {
- // fast-track for GL-enabled applications; just invalidate the whole hierarchy
- // with a null dirty rect, which tells the ViewRoot to redraw everything
- p.invalidateChild(this, null);
- return;
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
+ if (p != null && ai != null && ai.mHardwareAccelerated) {
+ // fast-track for GL-enabled applications; just invalidate the whole hierarchy
+ // with a null dirty rect, which tells the ViewRoot to redraw everything
+ p.invalidateChild(this, null);
+ return;
+ }
}
if (p != null && ai != null) {
final int scrollX = mScrollX;
@@ -6770,11 +6773,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mPrivateFlags |= INVALIDATED;
final ViewParent p = mParent;
final AttachInfo ai = mAttachInfo;
- if (p != null && ai != null && ai.mHardwareAccelerated) {
- // fast-track for GL-enabled applications; just invalidate the whole hierarchy
- // with a null dirty rect, which tells the ViewRoot to redraw everything
- p.invalidateChild(this, null);
- return;
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
+ if (p != null && ai != null && ai.mHardwareAccelerated) {
+ // fast-track for GL-enabled applications; just invalidate the whole hierarchy
+ // with a null dirty rect, which tells the ViewRoot to redraw everything
+ p.invalidateChild(this, null);
+ return;
+ }
}
if (p != null && ai != null && l < r && t < b) {
final int scrollX = mScrollX;
@@ -6823,11 +6829,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
final AttachInfo ai = mAttachInfo;
final ViewParent p = mParent;
- if (p != null && ai != null && ai.mHardwareAccelerated) {
- // fast-track for GL-enabled applications; just invalidate the whole hierarchy
- // with a null dirty rect, which tells the ViewRoot to redraw everything
- p.invalidateChild(this, null);
- return;
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
+ if (p != null && ai != null && ai.mHardwareAccelerated) {
+ // fast-track for GL-enabled applications; just invalidate the whole hierarchy
+ // with a null dirty rect, which tells the ViewRoot to redraw everything
+ p.invalidateChild(this, null);
+ return;
+ }
}
if (p != null && ai != null) {
@@ -8078,7 +8087,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*
* @return A HardwareLayer ready to render, or null if an error occurred.
*/
- HardwareLayer getHardwareLayer(Canvas currentCanvas) {
+ HardwareLayer getHardwareLayer() {
if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
return null;
}
@@ -8098,10 +8107,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mHardwareLayer.resize(width, height);
}
- final HardwareCanvas canvas = mHardwareLayer.start(mAttachInfo.mHardwareCanvas);
+ Canvas currentCanvas = mAttachInfo.mHardwareCanvas;
+ final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
+ mAttachInfo.mHardwareCanvas = canvas;
try {
canvas.setViewport(width, height);
- canvas.onPreDraw();
+ // TODO: We should pass the dirty rect
+ canvas.onPreDraw(null);
computeScroll();
canvas.translate(-mScrollX, -mScrollY);
@@ -8121,7 +8133,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
canvas.restoreToCount(restoreCount);
} finally {
canvas.onPostDraw();
- mHardwareLayer.end(mAttachInfo.mHardwareCanvas);
+ mHardwareLayer.end(currentCanvas);
+ mAttachInfo.mHardwareCanvas = currentCanvas;
}
}
@@ -8190,7 +8203,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
ViewGroup parent = (ViewGroup) this;
final int count = parent.getChildCount();
for (int i = 0; i < count; i++) {
- final View child = (View) parent.getChildAt(i);
+ final View child = parent.getChildAt(i);
child.outputDirtyFlags(indent + " ", clear, clearMask);
}
}
@@ -8251,7 +8264,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
int height = mBottom - mTop;
canvas.setViewport(width, height);
- canvas.onPreDraw();
+ // The dirty rect should always be null for a display list
+ canvas.onPreDraw(null);
final int restoreCount = canvas.save();
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c73cbe6..f198c46 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2395,8 +2395,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
canvas.scale(scale, scale);
}
}
-
- boolean layerSaved = false;
if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) {
if (transformToApply != null || !childHasIdentityMatrix) {
@@ -2477,7 +2475,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (hasNoCache) {
boolean layerRendered = false;
if (layerType == LAYER_TYPE_HARDWARE) {
- final HardwareLayer layer = child.getHardwareLayer(canvas);
+ final HardwareLayer layer = child.getHardwareLayer();
if (layer != null && layer.isValid()) {
((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, child.mLayerPaint);
layerRendered = true;
@@ -3357,7 +3355,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
addInArray(child, index);
child.mParent = this;
- child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK & ~DRAWING_CACHE_VALID) | DRAWN;
+ child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK & ~DRAWING_CACHE_VALID) |
+ DRAWN | INVALIDATED;
+ this.mPrivateFlags |= INVALIDATED;
if (child.hasFocus()) {
requestChildFocus(child, child.findFocus());
@@ -3527,10 +3527,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
(int) (boundingRect.bottom + 0.5f));
}
+ if (child.mLayerType != LAYER_TYPE_NONE) {
+ mPrivateFlags |= INVALIDATED;
+ mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ }
do {
View view = null;
if (parent instanceof View) {
view = (View) parent;
+ if (view.mLayerType != LAYER_TYPE_NONE &&
+ view.getParent() instanceof View) {
+ final View grandParent = (View) view.getParent();
+ grandParent.mPrivateFlags |= INVALIDATED;
+ grandParent.mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ }
}
if (drawAnimation) {
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index ba671c0..19d7811 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -160,7 +160,9 @@ public final class ViewRoot extends Handler implements ViewParent,
int mWidth;
int mHeight;
- Rect mDirty; // will be a graphics.Region soon
+ Rect mDirty;
+ final Rect mCurrentDirty = new Rect();
+ final Rect mPreviousDirty = new Rect();
boolean mIsAnimating;
CompatibilityInfo.Translator mTranslator;
@@ -1055,6 +1057,7 @@ public final class ViewRoot extends Handler implements ViewParent,
disposeResizeBitmap();
} else if (surfaceGenerationId != mSurface.getGenerationId() &&
mSurfaceHolder == null && mAttachInfo.mHardwareRenderer != null) {
+ fullRedrawNeeded = true;
mAttachInfo.mHardwareRenderer.updateSurface(mHolder);
}
} catch (RemoteException e) {
@@ -1488,10 +1491,15 @@ public final class ViewRoot extends Handler implements ViewParent,
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
if (!dirty.isEmpty() || mIsAnimating) {
mIsAnimating = false;
- dirty.setEmpty();
mHardwareYOffset = yoff;
mResizeAlpha = resizeAlpha;
- mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
+
+ mCurrentDirty.set(dirty);
+ mCurrentDirty.union(mPreviousDirty);
+ mPreviousDirty.set(dirty);
+ dirty.setEmpty();
+
+ mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this, mCurrentDirty);
}
if (animating) {
@@ -1986,6 +1994,7 @@ public final class ViewRoot extends Handler implements ViewParent,
if (mAttachInfo.mHardwareRenderer != null &&
mSurface != null && mSurface.isValid()) {
+ mFullRedrawNeeded = true;
mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
mAttachInfo, mHolder);
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 796af55..a107c60 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2706,7 +2706,7 @@ public class ListView extends AbsListView {
int startPos = (mSelectedPosition != INVALID_POSITION) ?
mSelectedPosition - 1 :
firstPosition + getChildCount() - 1;
- if (startPos < 0) {
+ if (startPos < 0 || startPos >= mAdapter.getCount()) {
return INVALID_POSITION;
}
if (startPos > last) {