diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 4 | ||||
| -rw-r--r-- | core/java/android/app/LoadedApk.java | 14 | ||||
| -rw-r--r-- | core/java/android/os/Message.java | 17 | ||||
| -rw-r--r-- | core/java/android/text/SpannableStringBuilder.java | 132 | ||||
| -rw-r--r-- | core/java/android/view/DisplayList.java | 24 | ||||
| -rw-r--r-- | core/java/android/view/GLES20Canvas.java | 7 | ||||
| -rw-r--r-- | core/java/android/view/GLES20DisplayList.java | 16 | ||||
| -rw-r--r-- | core/java/android/view/HardwareCanvas.java | 12 | ||||
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 74 | ||||
| -rwxr-xr-x | core/java/android/view/KeyEvent.java | 28 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 91 | ||||
| -rw-r--r-- | core/java/android/view/WindowManagerImpl.java | 7 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewClassic.java | 9 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewCore.java | 13 | ||||
| -rw-r--r-- | core/java/android/widget/RemoteViewsAdapter.java | 21 | ||||
| -rw-r--r-- | core/java/com/google/android/mms/pdu/PduPersister.java | 177 |
16 files changed, 397 insertions, 249 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index ab4e73d..98c4e10 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -174,8 +174,10 @@ public final class ActivityThread { static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>(); Instrumentation mInstrumentation; String mInstrumentationAppDir = null; + String mInstrumentationAppLibraryDir = null; String mInstrumentationAppPackage = null; String mInstrumentedAppDir = null; + String mInstrumentedAppLibraryDir = null; boolean mSystemThread = false; boolean mJitEnabled = false; @@ -3936,8 +3938,10 @@ public final class ActivityThread { } mInstrumentationAppDir = ii.sourceDir; + mInstrumentationAppLibraryDir = ii.nativeLibraryDir; mInstrumentationAppPackage = ii.packageName; mInstrumentedAppDir = data.info.getAppDir(); + mInstrumentedAppLibraryDir = data.info.getLibDir(); ApplicationInfo instrApp = new ApplicationInfo(); instrApp.packageName = ii.packageName; diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 5340fbb..8ab1ed6 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -261,6 +261,7 @@ public final class LoadedApk { if (mIncludeCode && !mPackageName.equals("android")) { String zip = mAppDir; + String libraryPath = mLibDir; /* * The following is a bit of a hack to inject @@ -273,15 +274,20 @@ public final class LoadedApk { String instrumentationAppDir = mActivityThread.mInstrumentationAppDir; + String instrumentationAppLibraryDir = + mActivityThread.mInstrumentationAppLibraryDir; String instrumentationAppPackage = mActivityThread.mInstrumentationAppPackage; String instrumentedAppDir = mActivityThread.mInstrumentedAppDir; + String instrumentedAppLibraryDir = + mActivityThread.mInstrumentedAppLibraryDir; String[] instrumentationLibs = null; if (mAppDir.equals(instrumentationAppDir) || mAppDir.equals(instrumentedAppDir)) { zip = instrumentationAppDir + ":" + instrumentedAppDir; + libraryPath = instrumentationAppLibraryDir + ":" + instrumentedAppLibraryDir; if (! instrumentedAppDir.equals(instrumentationAppDir)) { instrumentationLibs = getLibrariesFor(instrumentationAppPackage); @@ -301,7 +307,7 @@ public final class LoadedApk { */ if (ActivityThread.localLOGV) - Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + mLibDir); + Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + libraryPath); // Temporarily disable logging of disk reads on the Looper thread // as this is early and necessary. @@ -309,7 +315,7 @@ public final class LoadedApk { mClassLoader = ApplicationLoaders.getDefault().getClassLoader( - zip, mLibDir, mBaseClassLoader); + zip, libraryPath, mBaseClassLoader); initializeJavaContextClassLoader(); StrictMode.setThreadPolicy(oldPolicy); @@ -442,6 +448,10 @@ public final class LoadedApk { return mAppDir; } + public String getLibDir() { + return mLibDir; + } + public String getResDir() { return mResDir; } diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java index b816b11..4aa7fe2 100644 --- a/core/java/android/os/Message.java +++ b/core/java/android/os/Message.java @@ -16,9 +16,6 @@ package android.os; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; import android.util.TimeUtils; /** @@ -368,13 +365,13 @@ public final class Message implements Parcelable { * * Asynchronous messages represent interrupts or events that do not require global ordering * with represent to synchronous messages. Asynchronous messages are not subject to - * the synchronization barriers introduced by {@link MessageQueue#acquireSyncBarrier()}. + * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @return True if the message is asynchronous. * * @see #setAsynchronous(boolean) - * @see MessageQueue#acquireSyncBarrier() - * @see MessageQueue#releaseSyncBarrier() + * @see MessageQueue#enqueueSyncBarrier(long) + * @see MessageQueue#removeSyncBarrier(int) * * @hide */ @@ -387,13 +384,13 @@ public final class Message implements Parcelable { * * Asynchronous messages represent interrupts or events that do not require global ordering * with represent to synchronous messages. Asynchronous messages are not subject to - * the synchronization barriers introduced by {@link MessageQueue#acquireSyncBarrier()}. + * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param async True if the message is asynchronous. * * @see #isAsynchronous() - * @see MessageQueue#acquireSyncBarrier() - * @see MessageQueue#releaseSyncBarrier() + * @see MessageQueue#enqueueSyncBarrier(long) + * @see MessageQueue#removeSyncBarrier(int) * * @hide */ @@ -506,7 +503,7 @@ public final class Message implements Parcelable { Messenger.writeMessengerOrNullToParcel(replyTo, dest); } - private final void readFromParcel(Parcel source) { + private void readFromParcel(Parcel source) { what = source.readInt(); arg1 = source.readInt(); arg2 = source.readInt(); diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java index d0c87c6..f7a7eb8 100644 --- a/core/java/android/text/SpannableStringBuilder.java +++ b/core/java/android/text/SpannableStringBuilder.java @@ -262,19 +262,8 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable return append(String.valueOf(text)); } - private int change(int start, int end, CharSequence tb, int tbstart, int tbend) { - return change(true, start, end, tb, tbstart, tbend); - } - - private int change(boolean notify, int start, int end, - CharSequence tb, int tbstart, int tbend) { + private void change(int start, int end, CharSequence tb, int tbstart, int tbend) { checkRange("replace", start, end); - int ret = tbend - tbstart; - TextWatcher[] recipients = null; - - if (notify) { - recipients = sendTextWillChange(start, end - start, tbend - tbstart); - } for (int i = mSpanCount - 1; i >= 0; i--) { if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) { @@ -338,7 +327,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable en = tbend; if (getSpanStart(spans[i]) < 0) { - setSpan(true, spans[i], + setSpan(false, spans[i], st - tbstart + start, en - tbstart + start, sp.getSpanFlags(spans[i])); @@ -346,51 +335,37 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } } - // no need for span fixup on pure insertion - if (tbend > tbstart && end - start == 0) { - if (notify) { - sendTextChange(recipients, start, end - start, tbend - tbstart); - sendTextHasChanged(recipients); - } - - return ret; - } - - boolean atend = (mGapStart + mGapLength == mText.length); + if (end > start) { + // no need for span fixup on pure insertion + boolean atEnd = (mGapStart + mGapLength == mText.length); - for (int i = mSpanCount - 1; i >= 0; i--) { - if (mSpanStarts[i] >= start && - mSpanStarts[i] < mGapStart + mGapLength) { - int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; + for (int i = mSpanCount - 1; i >= 0; i--) { + if (mSpanStarts[i] >= start && + mSpanStarts[i] < mGapStart + mGapLength) { + int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; - if (flag == POINT || (flag == PARAGRAPH && atend)) + if (flag == POINT || (flag == PARAGRAPH && atEnd)) mSpanStarts[i] = mGapStart + mGapLength; else mSpanStarts[i] = start; - } + } - if (mSpanEnds[i] >= start && - mSpanEnds[i] < mGapStart + mGapLength) { - int flag = (mSpanFlags[i] & END_MASK); + if (mSpanEnds[i] >= start && + mSpanEnds[i] < mGapStart + mGapLength) { + int flag = (mSpanFlags[i] & END_MASK); - if (flag == POINT || (flag == PARAGRAPH && atend)) - mSpanEnds[i] = mGapStart + mGapLength; - else - mSpanEnds[i] = start; - } + if (flag == POINT || (flag == PARAGRAPH && atEnd)) + mSpanEnds[i] = mGapStart + mGapLength; + else + mSpanEnds[i] = start; + } - // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE - if (mSpanEnds[i] < mSpanStarts[i]) { - removeSpan(i); + // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE + if (mSpanEnds[i] < mSpanStarts[i]) { + removeSpan(i); + } } } - - if (notify) { - sendTextChange(recipients, start, end - start, tbend - tbstart); - sendTextHasChanged(recipients); - } - - return ret; } private void removeSpan(int i) { @@ -425,8 +400,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable CharSequence tb, int tbstart, int tbend) { int filtercount = mFilters.length; for (int i = 0; i < filtercount; i++) { - CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, - this, start, end); + CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, this, start, end); if (repl != null) { tb = repl; @@ -435,11 +409,17 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } } - if (end == start && tbstart == tbend) { + final int origLen = end - start; + final int newLen = tbend - tbstart; + + if (origLen == 0 && newLen == 0) { return this; } - if (end == start || tbstart == tbend) { + TextWatcher[] textWatchers = getSpans(start, start + origLen, TextWatcher.class); + sendBeforeTextChanged(textWatchers, start, origLen, newLen); + + if (origLen == 0 || newLen == 0) { change(start, end, tb, tbstart, tbend); } else { int selstart = Selection.getSelectionStart(this); @@ -450,11 +430,6 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable checkRange("replace", start, end); moveGapTo(end); - TextWatcher[] recipients; - - int origlen = end - start; - - recipients = sendTextWillChange(start, origlen, tbend - tbstart); if (mGapLength < 2) resizeFor(length() + 1); @@ -475,9 +450,9 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable new Exception("mGapLength < 1").printStackTrace(); } - int inserted = change(false, start + 1, start + 1, tb, tbstart, tbend); - change(false, start, start + 1, "", 0, 0); - change(false, start + inserted, start + inserted + origlen, "", 0, 0); + change(start + 1, start + 1, tb, tbstart, tbend); + change(start, start + 1, "", 0, 0); + change(start + newLen, start + newLen + origLen, "", 0, 0); /* * Special case to keep the cursor in the same position @@ -490,7 +465,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (selstart > start && selstart < end) { long off = selstart - start; - off = off * inserted / (end - start); + off = off * newLen / (end - start); selstart = (int) off + start; setSpan(false, Selection.SELECTION_START, selstart, selstart, @@ -499,15 +474,16 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (selend > start && selend < end) { long off = selend - start; - off = off * inserted / (end - start); + off = off * newLen / (end - start); selend = (int) off + start; setSpan(false, Selection.SELECTION_END, selend, selend, Spanned.SPAN_POINT_POINT); } - sendTextChange(recipients, start, origlen, inserted); - sendTextHasChanged(recipients); } + sendTextChanged(textWatchers, start, origLen, newLen); + sendAfterTextChanged(textWatchers); + return this; } @@ -872,30 +848,27 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable return new String(buf); } - private TextWatcher[] sendTextWillChange(int start, int before, int after) { - TextWatcher[] recip = getSpans(start, start + before, TextWatcher.class); - int n = recip.length; + private void sendBeforeTextChanged(TextWatcher[] watchers, int start, int before, int after) { + int n = watchers.length; for (int i = 0; i < n; i++) { - recip[i].beforeTextChanged(this, start, before, after); + watchers[i].beforeTextChanged(this, start, before, after); } - - return recip; } - private void sendTextChange(TextWatcher[] recip, int start, int before, int after) { - int n = recip.length; + private void sendTextChanged(TextWatcher[] watchers, int start, int before, int after) { + int n = watchers.length; for (int i = 0; i < n; i++) { - recip[i].onTextChanged(this, start, before, after); + watchers[i].onTextChanged(this, start, before, after); } } - private void sendTextHasChanged(TextWatcher[] recip) { - int n = recip.length; + private void sendAfterTextChanged(TextWatcher[] watchers) { + int n = watchers.length; for (int i = 0; i < n; i++) { - recip[i].afterTextChanged(this); + watchers[i].afterTextChanged(this); } } @@ -1037,8 +1010,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable * Don't call this yourself -- exists for Canvas to use internally. * {@hide} */ - public void drawText(Canvas c, int start, int end, - float x, float y, Paint p) { + public void drawText(Canvas c, int start, int end, float x, float y, Paint p) { checkRange("drawText", start, end); if (end <= mGapStart) { @@ -1059,8 +1031,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable * Don't call this yourself -- exists for Canvas to use internally. * {@hide} */ - public void drawTextRun(Canvas c, int start, int end, - int contextStart, int contextEnd, + public void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd, float x, float y, int flags, Paint p) { checkRange("drawTextRun", start, end); @@ -1262,6 +1233,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable private int[] mSpanFlags; private int mSpanCount; + // TODO These value are tightly related to the public SPAN_MARK/POINT values in {@link Spanned} private static final int POINT = 2; private static final int PARAGRAPH = 3; diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java index e2aafa9..33631b7 100644 --- a/core/java/android/view/DisplayList.java +++ b/core/java/android/view/DisplayList.java @@ -16,6 +16,8 @@ package android.view; +import android.graphics.Matrix; + /** * A display lists records a series of graphics related operation and can replay * them later. Display lists are usually built by recording operations on a @@ -117,12 +119,26 @@ public abstract class DisplayList { public abstract void setClipChildren(boolean clipChildren); /** - * Set the application scale on the DisplayList. This scale is incurred by applications that - * are auto-scaled for compatibility reasons. By default, the value is 1 (unscaled). + * Set the static matrix on the DisplayList. This matrix exists if a custom ViewGroup + * overrides + * {@link ViewGroup#getChildStaticTransformation(View, android.view.animation.Transformation)} + * and also has {@link ViewGroup#setStaticTransformationsEnabled(boolean)} set to true. + * This matrix will be concatenated with any other matrices in the DisplayList to position + * the view appropriately. + * + * @param matrix The matrix + */ + public abstract void setStaticMatrix(Matrix matrix); + + /** + * Set the Animation matrix on the DisplayList. This matrix exists if an Animation is + * currently playing on a View, and is set on the DisplayList during at draw() time. When + * the Animation finishes, the matrix should be cleared by sending <code>null</code> + * for the matrix parameter. * - * @param scale The scaling factor + * @param matrix The matrix, null indicates that the matrix should be cleared. */ - public abstract void setApplicationScale(float scale); + public abstract void setAnimationMatrix(Matrix matrix); /** * Sets the alpha value for the DisplayList diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 5b0433e..bedafc7 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -259,6 +259,13 @@ class GLES20Canvas extends HardwareCanvas { private static native int nCallDrawGLFunction(int renderer, int drawGLFunction); + @Override + public int invokeFunctors(Rect dirty) { + return nInvokeFunctors(mRenderer, dirty); + } + + private static native int nInvokeFunctors(int renderer, Rect dirty); + /////////////////////////////////////////////////////////////////////////// // Memory /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java index 9b4cf21..bc3bce0 100644 --- a/core/java/android/view/GLES20DisplayList.java +++ b/core/java/android/view/GLES20DisplayList.java @@ -17,6 +17,7 @@ package android.view; import android.graphics.Bitmap; +import android.graphics.Matrix; import java.util.ArrayList; @@ -119,9 +120,18 @@ class GLES20DisplayList extends DisplayList { } @Override - public void setApplicationScale(float scale) { + public void setStaticMatrix(Matrix matrix) { try { - nSetApplicationScale(getNativeDisplayList(), scale); + nSetStaticMatrix(getNativeDisplayList(), matrix.native_instance); + } catch (IllegalStateException e) { + // invalid DisplayList okay: we'll set current values the next time we render to it + } + } + + @Override + public void setAnimationMatrix(Matrix matrix) { + try { + nSetAnimationMatrix(getNativeDisplayList(), matrix.native_instance); } catch (IllegalStateException e) { // invalid DisplayList okay: we'll set current values the next time we render to it } @@ -335,6 +345,8 @@ class GLES20DisplayList extends DisplayList { private static native void nSetTransformationInfo(int displayList, float alpha, float translationX, float translationY, float rotation, float rotationX, float rotationY, float scaleX, float scaleY); + private static native void nSetStaticMatrix(int displayList, int nativeMatrix); + private static native void nSetAnimationMatrix(int displayList, int animationMatrix); /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java index 2636ea2..de8c62d 100644 --- a/core/java/android/view/HardwareCanvas.java +++ b/core/java/android/view/HardwareCanvas.java @@ -98,4 +98,16 @@ public abstract class HardwareCanvas extends Canvas { // Noop - this is done in the display list recorder subclass return DisplayList.STATUS_DONE; } + + /** + * Invoke all the functors who requested to be invoked during the previous frame. + * + * @param dirty The region to redraw when the functors return {@link DisplayList#STATUS_DRAW} + * + * @return One of {@link DisplayList#STATUS_DONE}, {@link DisplayList#STATUS_DRAW} or + * {@link DisplayList#STATUS_INVOKE} + */ + public int invokeFunctors(Rect dirty) { + return DisplayList.STATUS_DONE; + } } diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index be640dc..b100a0c 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -259,7 +259,14 @@ public abstract class HardwareRenderer { * @param pw */ abstract void dumpGfxInfo(PrintWriter pw); - + + /** + * Outputs the total number of frames rendered (used for fps calculations) + * + * @return the number of frames rendered + */ + abstract long getFrameCount(); + /** * Sets the directory to use as a persistent storage for hardware rendering * resources. @@ -495,7 +502,9 @@ public abstract class HardwareRenderer { static final int SURFACE_STATE_ERROR = 0; static final int SURFACE_STATE_SUCCESS = 1; static final int SURFACE_STATE_UPDATED = 2; - + + static final int FUNCTOR_PROCESS_DELAY = 2; + static EGL10 sEgl; static EGLDisplay sEglDisplay; static EGLConfig sEglConfig; @@ -513,7 +522,7 @@ public abstract class HardwareRenderer { GL mGl; HardwareCanvas mCanvas; - int mFrameCount; + long mFrameCount; Paint mDebugPaint; static boolean sDirtyRegions; @@ -542,7 +551,9 @@ public abstract class HardwareRenderer { private boolean mDestroyed; private final Rect mRedrawClip = new Rect(); + private final int[] mSurfaceSize = new int[2]; + private final FunctorsRunnable mFunctorsRunnable = new FunctorsRunnable(); GlRenderer(int glVersion, boolean translucent) { mGlVersion = glVersion; @@ -591,6 +602,11 @@ public abstract class HardwareRenderer { } } + @Override + long getFrameCount() { + return mFrameCount; + } + /** * Indicates whether this renderer instance can track and update dirty regions. */ @@ -945,6 +961,24 @@ public abstract class HardwareRenderer { void onPostDraw() { } + class FunctorsRunnable implements Runnable { + View.AttachInfo attachInfo; + + @Override + public void run() { + final HardwareRenderer renderer = attachInfo.mHardwareRenderer; + if (renderer == null || !renderer.isEnabled() || renderer != GlRenderer.this) { + return; + } + + final int surfaceState = checkCurrent(); + if (surfaceState != SURFACE_STATE_ERROR) { + int status = mCanvas.invokeFunctors(mRedrawClip); + handleFunctorStatus(attachInfo, status); + } + } + } + @Override boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) { @@ -1039,15 +1073,7 @@ public abstract class HardwareRenderer { } } - if (status != DisplayList.STATUS_DONE) { - if (mRedrawClip.isEmpty()) { - attachInfo.mViewRootImpl.invalidate(); - } else { - attachInfo.mViewRootImpl.invalidateChildInParent( - null, mRedrawClip); - mRedrawClip.setEmpty(); - } - } + handleFunctorStatus(attachInfo, status); } else { // Shouldn't reach here view.draw(canvas); @@ -1056,13 +1082,13 @@ public abstract class HardwareRenderer { callbacks.onHardwarePostDraw(canvas); canvas.restoreToCount(saveCount); view.mRecreateDisplayList = false; - + mFrameCount++; if (mDebugDirtyRegions) { if (mDebugPaint == null) { mDebugPaint = new Paint(); mDebugPaint.setColor(0x7fff0000); } - if (dirty != null && (mFrameCount++ & 1) == 0) { + if (dirty != null && (mFrameCount & 1) == 0) { canvas.drawRect(dirty, mDebugPaint); } } @@ -1099,6 +1125,26 @@ public abstract class HardwareRenderer { return false; } + private void handleFunctorStatus(View.AttachInfo attachInfo, int status) { + // If the draw flag is set, functors will be invoked while executing + // the tree of display lists + if ((status & DisplayList.STATUS_DRAW) != 0) { + if (mRedrawClip.isEmpty()) { + attachInfo.mViewRootImpl.invalidate(); + } else { + attachInfo.mViewRootImpl.invalidateChildInParent(null, mRedrawClip); + mRedrawClip.setEmpty(); + } + } + + if ((status & DisplayList.STATUS_INVOKE) != 0) { + attachInfo.mHandler.removeCallbacks(mFunctorsRunnable); + mFunctorsRunnable.attachInfo = attachInfo; + // delay the functor callback by a few ms so it isn't polled constantly + attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY); + } + } + /** * Ensures the current EGL context is the one we expect. * diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 104ed6a..e4a4a75 100755 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -591,8 +591,24 @@ public class KeyEvent extends InputEvent implements Parcelable { /** Key code constant: Calculator special function key. * Used to launch a calculator application. */ public static final int KEYCODE_CALCULATOR = 210; - - private static final int LAST_KEYCODE = KEYCODE_CALCULATOR; + /** Key code constant: Japanese full-width / half-width key. */ + public static final int KEYCODE_ZENKAKU_HANKAKU = 211; + /** Key code constant: Japanese alphanumeric key. */ + public static final int KEYCODE_EISU = 212; + /** Key code constant: Japanese non-conversion key. */ + public static final int KEYCODE_MUHENKAN = 213; + /** Key code constant: Japanese conversion key. */ + public static final int KEYCODE_HENKAN = 214; + /** Key code constant: Japanese katakana / hiragana key. */ + public static final int KEYCODE_KATAKANA_HIRAGANA = 215; + /** Key code constant: Japanese Yen key. */ + public static final int KEYCODE_YEN = 216; + /** Key code constant: Japanese Ro key. */ + public static final int KEYCODE_RO = 217; + /** Key code constant: Japanese kana key. */ + public static final int KEYCODE_KANA = 218; + + private static final int LAST_KEYCODE = KEYCODE_KANA; // NOTE: If you add a new keycode here you must also add it to: // isSystem() @@ -825,6 +841,14 @@ public class KeyEvent extends InputEvent implements Parcelable { names.append(KEYCODE_CALENDAR, "KEYCODE_CALENDAR"); names.append(KEYCODE_MUSIC, "KEYCODE_MUSIC"); names.append(KEYCODE_CALCULATOR, "KEYCODE_CALCULATOR"); + names.append(KEYCODE_ZENKAKU_HANKAKU, "KEYCODE_ZENKAKU_HANKAKU"); + names.append(KEYCODE_EISU, "KEYCODE_EISU"); + names.append(KEYCODE_MUHENKAN, "KEYCODE_MUHENKAN"); + names.append(KEYCODE_HENKAN, "KEYCODE_HENKAN"); + names.append(KEYCODE_KATAKANA_HIRAGANA, "KEYCODE_KATAKANA_HIRAGANA"); + names.append(KEYCODE_YEN, "KEYCODE_YEN"); + names.append(KEYCODE_RO, "KEYCODE_RO"); + names.append(KEYCODE_KANA, "KEYCODE_KANA"); }; // Symbolic names of all metakeys in bit order from least significant to most significant. diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 81f3f6a..18e1697 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1464,7 +1464,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * apps. * @hide */ - public static final boolean USE_DISPLAY_LIST_PROPERTIES = false; + public static final boolean USE_DISPLAY_LIST_PROPERTIES = true; /** * Map used to store views' tags. @@ -11529,12 +11529,34 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal displayList.setClipChildren( (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0); } - if (mAttachInfo != null && mAttachInfo.mScalingRequired && - mAttachInfo.mApplicationScale != 1.0f) { - displayList.setApplicationScale(1f / mAttachInfo.mApplicationScale); + float alpha = 1; + if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags & + ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { + ViewGroup parentVG = (ViewGroup) mParent; + final boolean hasTransform = + parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation); + if (hasTransform) { + Transformation transform = parentVG.mChildTransformation; + final int transformType = parentVG.mChildTransformation.getTransformationType(); + if (transformType != Transformation.TYPE_IDENTITY) { + if ((transformType & Transformation.TYPE_ALPHA) != 0) { + alpha = transform.getAlpha(); + } + if ((transformType & Transformation.TYPE_MATRIX) != 0) { + displayList.setStaticMatrix(transform.getMatrix()); + } + } + } } if (mTransformationInfo != null) { - displayList.setTransformationInfo(mTransformationInfo.mAlpha, + alpha *= mTransformationInfo.mAlpha; + if (alpha < 1) { + final int multipliedAlpha = (int) (255 * alpha); + if (onSetAlpha(multipliedAlpha)) { + alpha = 1; + } + } + displayList.setTransformationInfo(alpha, mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY, mTransformationInfo.mRotation, mTransformationInfo.mRotationX, mTransformationInfo.mRotationY, mTransformationInfo.mScaleX, @@ -11548,6 +11570,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal displayList.setPivotX(getPivotX()); displayList.setPivotY(getPivotY()); } + } else if (alpha < 1) { + displayList.setAlpha(alpha); } } } @@ -11580,6 +11604,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 || (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) { caching = true; + // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired; } else { caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated; @@ -11590,7 +11615,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal more = drawAnimation(parent, drawingTime, a, scalingRequired); concatMatrix = a.willChangeTransformationMatrix(); transformToApply = parent.mChildTransformation; - } else if ((flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { + } else if (!useDisplayListProperties && + (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { final boolean hasTransform = parent.getChildStaticTransformation(this, parent.mChildTransformation); if (hasTransform) { @@ -11658,6 +11684,17 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } useDisplayListProperties &= hasDisplayList; + if (useDisplayListProperties) { + displayList = getDisplayList(); + if (!displayList.isValid()) { + // Uncommon, but possible. If a view is removed from the hierarchy during the call + // to getDisplayList(), the display list will be marked invalid and we should not + // try to use it again. + displayList = null; + hasDisplayList = false; + useDisplayListProperties = false; + } + } final boolean hasNoCache = cache == null || hasDisplayList; final boolean offsetForScroll = cache == null && !hasDisplayList && @@ -11675,6 +11712,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } if (scalingRequired) { if (useDisplayListProperties) { + // TODO: Might not need this if we put everything inside the DL restoreTo = canvas.save(); } // mAttachInfo cannot be null, otherwise scalingRequired == false @@ -11684,7 +11722,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } float alpha = useDisplayListProperties ? 1 : getAlpha(); - if (transformToApply != null || alpha < 1.0f || !hasIdentityMatrix()) { + if (transformToApply != null || alpha < 1 || !hasIdentityMatrix()) { if (transformToApply != null || !childHasIdentityMatrix) { int transX = 0; int transY = 0; @@ -11696,16 +11734,20 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (transformToApply != null) { if (concatMatrix) { - // Undo the scroll translation, apply the transformation matrix, - // then redo the scroll translate to get the correct result. - canvas.translate(-transX, -transY); - canvas.concat(transformToApply.getMatrix()); - canvas.translate(transX, transY); + if (useDisplayListProperties) { + displayList.setAnimationMatrix(transformToApply.getMatrix()); + } else { + // Undo the scroll translation, apply the transformation matrix, + // then redo the scroll translate to get the correct result. + canvas.translate(-transX, -transY); + canvas.concat(transformToApply.getMatrix()); + canvas.translate(transX, transY); + } parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; } float transformAlpha = transformToApply.getAlpha(); - if (transformAlpha < 1.0f) { + if (transformAlpha < 1) { alpha *= transformToApply.getAlpha(); parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; } @@ -11718,7 +11760,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } - if (alpha < 1.0f) { + if (alpha < 1) { parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; if (hasNoCache) { final int multipliedAlpha = (int) (255 * alpha); @@ -11728,7 +11770,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal layerType != LAYER_TYPE_NONE) { layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG; } - if (layerType == LAYER_TYPE_NONE) { + if (useDisplayListProperties) { + displayList.setAlpha(alpha * getAlpha()); + } else if (layerType == LAYER_TYPE_NONE) { final int scrollX = hasDisplayList ? 0 : sx; final int scrollY = hasDisplayList ? 0 : sy; canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft, @@ -11758,7 +11802,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } - if (hasDisplayList) { + if (!useDisplayListProperties && hasDisplayList) { displayList = getDisplayList(); if (!displayList.isValid()) { // Uncommon, but possible. If a view is removed from the hierarchy during the call @@ -11815,7 +11859,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal cachePaint.setDither(false); parent.mCachePaint = cachePaint; } - if (alpha < 1.0f) { + if (alpha < 1) { cachePaint.setAlpha((int) (alpha * 255)); parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE; } else if ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) { @@ -13614,13 +13658,12 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal mPrivateFlags |= FORCE_LAYOUT; mPrivateFlags |= INVALIDATED; - if (mParent != null) { - if (mLayoutParams != null) { - mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection()); - } - if (!mParent.isLayoutRequested()) { - mParent.requestLayout(); - } + if (mLayoutParams != null) { + mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection()); + } + + if (mParent != null && !mParent.isLayoutRequested()) { + mParent.requestLayout(); } } diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index f2ee9f9..a45a87e 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -510,8 +510,13 @@ public class WindowManagerImpl implements WindowManager { String name = root.getClass().getName() + '@' + Integer.toHexString(hashCode()); - pw.printf(" %s: %d views, %.2f kB (display lists)\n", + pw.printf(" %s: %d views, %.2f kB (display lists)", name, info[0], info[1] / 1024.0f); + HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer; + if (renderer != null) { + pw.printf(", %d frames rendered", renderer.getFrameCount()); + } + pw.printf("\n"); viewsCount += info[0]; displayListsSize += info[1]; diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index 04fa07a..45c5fa0 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -1204,10 +1204,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc static final int SHOW_FULLSCREEN = 120; static final int HIDE_FULLSCREEN = 121; static final int REPLACE_BASE_CONTENT = 123; - static final int FORM_DID_BLUR = 124; static final int UPDATE_MATCH_COUNT = 126; static final int CENTER_FIT_RECT = 127; - static final int REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID = 128; static final int SET_SCROLLBAR_MODES = 129; static final int SELECTION_STRING_CHANGED = 130; static final int HIT_TEST_RESULT = 131; @@ -1274,7 +1272,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc "HIDE_FULLSCREEN", // = 121; "DOM_FOCUS_CHANGED", // = 122; "REPLACE_BASE_CONTENT", // = 123; - "FORM_DID_BLUR", // = 124; "RETURN_LABEL", // = 125; "UPDATE_MATCH_COUNT", // = 126; "CENTER_FIT_RECT", // = 127; @@ -8288,16 +8285,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } } break; - case REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID: - displaySoftKeyboard(true); - // fall through to UPDATE_TEXT_SELECTION_MSG_ID case UPDATE_TEXT_SELECTION_MSG_ID: updateTextSelectionFromMessage(msg.arg1, msg.arg2, (WebViewCore.TextSelectionData) msg.obj); break; - case FORM_DID_BLUR: - // TODO: Figure out if this is needed for something (b/6111763) - break; case TAKE_FOCUS: int direction = msg.arg1; View focusSearch = mWebView.focusSearch(direction); diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 3eba6d7..b4ebc09 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -325,17 +325,6 @@ public final class WebViewCore { } /** - * Called by JNI. Send a message to the UI thread to hide the soft keyboard - * if the node pointed to by nodePointer is still in focus. - * @param nodePointer The node which just blurred. - */ - private void formDidBlur(int nodePointer) { - if (mWebViewClassic == null) return; - Message.obtain(mWebViewClassic.mPrivateHandler, WebViewClassic.FORM_DID_BLUR, - nodePointer, 0).sendToTarget(); - } - - /** * Called by JNI when the focus node changed. */ private void focusNodeChanged(int nodePointer, WebKitHitTest hitTest) { @@ -2830,7 +2819,7 @@ public final class WebViewCore { Message.obtain(mWebViewClassic.mPrivateHandler, WebViewClassic.INIT_EDIT_FIELD, initData).sendToTarget(); Message.obtain(mWebViewClassic.mPrivateHandler, - WebViewClassic.REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID, + WebViewClassic.UPDATE_TEXT_SELECTION_MSG_ID, initData.mFieldPointer, 0, new TextSelectionData(start, end, selectionPtr)) .sendToTarget(); diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java index 586fdf4..8067435 100644 --- a/core/java/android/widget/RemoteViewsAdapter.java +++ b/core/java/android/widget/RemoteViewsAdapter.java @@ -477,8 +477,11 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback private static final String TAG = "FixedSizeRemoteViewsCache"; // The meta data related to all the RemoteViews, ie. count, is stable, etc. - private RemoteViewsMetaData mMetaData; - private RemoteViewsMetaData mTemporaryMetaData; + // The meta data objects are made final so that they can be locked on independently + // of the FixedSizeRemoteViewsCache. If we ever lock on both meta data objects, it is in + // the order mTemporaryMetaData followed by mMetaData. + private final RemoteViewsMetaData mMetaData; + private final RemoteViewsMetaData mTemporaryMetaData; // The cache/mapping of position to RemoteViewsMetaData. This set is guaranteed to be // greater than or equal to the set of RemoteViews. @@ -939,6 +942,10 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback * which wouldn't otherwise be possible. */ public void setVisibleRangeHint(int lowerBound, int upperBound) { + if (lowerBound < 0 || upperBound < 0) { + throw new RuntimeException("Attempted to set invalid range: lowerBound="+lowerBound + + "," + "upperBound="+upperBound); + } mVisibleWindowLowerBound = lowerBound; mVisibleWindowUpperBound = upperBound; } @@ -1072,12 +1079,20 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback // Re-request the new metadata (only after the notification to the factory) updateTemporaryMetaData(); + int newCount; + synchronized(mCache.getTemporaryMetaData()) { + newCount = mCache.getTemporaryMetaData().count; + } // Pre-load (our best guess of) the views which are currently visible in the AdapterView. // This mitigates flashing and flickering of loading views when a widget notifies that // its data has changed. for (int i = mVisibleWindowLowerBound; i <= mVisibleWindowUpperBound; i++) { - updateRemoteViews(i, false, false); + // Because temporary meta data is only ever modified from this thread (ie. + // mWorkerThread), it is safe to assume that count is a valid representation. + if (i < newCount) { + updateRemoteViews(i, false, false); + } } // Propagate the notification back to the base adapter diff --git a/core/java/com/google/android/mms/pdu/PduPersister.java b/core/java/com/google/android/mms/pdu/PduPersister.java index 7c937ed..1a8e80f 100644 --- a/core/java/com/google/android/mms/pdu/PduPersister.java +++ b/core/java/com/google/android/mms/pdu/PduPersister.java @@ -519,98 +519,99 @@ public class PduPersister { * @throws MmsException Failed to load some fields of a PDU. */ public GenericPdu load(Uri uri) throws MmsException { - PduCacheEntry cacheEntry; - synchronized(PDU_CACHE_INSTANCE) { - if (PDU_CACHE_INSTANCE.isUpdating(uri)) { - if (LOCAL_LOGV) { - Log.v(TAG, "load: " + uri + " blocked by isUpdating()"); - } - try { - PDU_CACHE_INSTANCE.wait(); - } catch (InterruptedException e) { - Log.e(TAG, "load: ", e); - } - cacheEntry = PDU_CACHE_INSTANCE.get(uri); - if (cacheEntry != null) { - return cacheEntry.getPdu(); + GenericPdu pdu = null; + PduCacheEntry cacheEntry = null; + int msgBox = 0; + long threadId = -1; + try { + synchronized(PDU_CACHE_INSTANCE) { + if (PDU_CACHE_INSTANCE.isUpdating(uri)) { + if (LOCAL_LOGV) { + Log.v(TAG, "load: " + uri + " blocked by isUpdating()"); + } + try { + PDU_CACHE_INSTANCE.wait(); + } catch (InterruptedException e) { + Log.e(TAG, "load: ", e); + } + cacheEntry = PDU_CACHE_INSTANCE.get(uri); + if (cacheEntry != null) { + return cacheEntry.getPdu(); + } } + // Tell the cache to indicate to other callers that this item + // is currently being updated. + PDU_CACHE_INSTANCE.setUpdating(uri, true); } - // Tell the cache to indicate to other callers that this item - // is currently being updated. - PDU_CACHE_INSTANCE.setUpdating(uri, true); - } - Cursor c = SqliteWrapper.query(mContext, mContentResolver, uri, - PDU_PROJECTION, null, null, null); - PduHeaders headers = new PduHeaders(); - Set<Entry<Integer, Integer>> set; - long msgId = ContentUris.parseId(uri); - int msgBox; - long threadId; + Cursor c = SqliteWrapper.query(mContext, mContentResolver, uri, + PDU_PROJECTION, null, null, null); + PduHeaders headers = new PduHeaders(); + Set<Entry<Integer, Integer>> set; + long msgId = ContentUris.parseId(uri); - try { - if ((c == null) || (c.getCount() != 1) || !c.moveToFirst()) { - throw new MmsException("Bad uri: " + uri); - } + try { + if ((c == null) || (c.getCount() != 1) || !c.moveToFirst()) { + throw new MmsException("Bad uri: " + uri); + } - msgBox = c.getInt(PDU_COLUMN_MESSAGE_BOX); - threadId = c.getLong(PDU_COLUMN_THREAD_ID); + msgBox = c.getInt(PDU_COLUMN_MESSAGE_BOX); + threadId = c.getLong(PDU_COLUMN_THREAD_ID); - set = ENCODED_STRING_COLUMN_INDEX_MAP.entrySet(); - for (Entry<Integer, Integer> e : set) { - setEncodedStringValueToHeaders( - c, e.getValue(), headers, e.getKey()); - } + set = ENCODED_STRING_COLUMN_INDEX_MAP.entrySet(); + for (Entry<Integer, Integer> e : set) { + setEncodedStringValueToHeaders( + c, e.getValue(), headers, e.getKey()); + } - set = TEXT_STRING_COLUMN_INDEX_MAP.entrySet(); - for (Entry<Integer, Integer> e : set) { - setTextStringToHeaders( - c, e.getValue(), headers, e.getKey()); - } + set = TEXT_STRING_COLUMN_INDEX_MAP.entrySet(); + for (Entry<Integer, Integer> e : set) { + setTextStringToHeaders( + c, e.getValue(), headers, e.getKey()); + } - set = OCTET_COLUMN_INDEX_MAP.entrySet(); - for (Entry<Integer, Integer> e : set) { - setOctetToHeaders( - c, e.getValue(), headers, e.getKey()); - } + set = OCTET_COLUMN_INDEX_MAP.entrySet(); + for (Entry<Integer, Integer> e : set) { + setOctetToHeaders( + c, e.getValue(), headers, e.getKey()); + } - set = LONG_COLUMN_INDEX_MAP.entrySet(); - for (Entry<Integer, Integer> e : set) { - setLongToHeaders( - c, e.getValue(), headers, e.getKey()); - } - } finally { - if (c != null) { - c.close(); + set = LONG_COLUMN_INDEX_MAP.entrySet(); + for (Entry<Integer, Integer> e : set) { + setLongToHeaders( + c, e.getValue(), headers, e.getKey()); + } + } finally { + if (c != null) { + c.close(); + } } - } - - // Check whether 'msgId' has been assigned a valid value. - if (msgId == -1L) { - throw new MmsException("Error! ID of the message: -1."); - } - // Load address information of the MM. - loadAddress(msgId, headers); - - int msgType = headers.getOctet(PduHeaders.MESSAGE_TYPE); - PduBody body = new PduBody(); + // Check whether 'msgId' has been assigned a valid value. + if (msgId == -1L) { + throw new MmsException("Error! ID of the message: -1."); + } - // For PDU which type is M_retrieve.conf or Send.req, we should - // load multiparts and put them into the body of the PDU. - if ((msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) - || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) { - PduPart[] parts = loadParts(msgId); - if (parts != null) { - int partsNum = parts.length; - for (int i = 0; i < partsNum; i++) { - body.addPart(parts[i]); + // Load address information of the MM. + loadAddress(msgId, headers); + + int msgType = headers.getOctet(PduHeaders.MESSAGE_TYPE); + PduBody body = new PduBody(); + + // For PDU which type is M_retrieve.conf or Send.req, we should + // load multiparts and put them into the body of the PDU. + if ((msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) + || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) { + PduPart[] parts = loadParts(msgId); + if (parts != null) { + int partsNum = parts.length; + for (int i = 0; i < partsNum; i++) { + body.addPart(parts[i]); + } } } - } - GenericPdu pdu = null; - switch (msgType) { + switch (msgType) { case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND: pdu = new NotificationInd(headers); break; @@ -657,16 +658,20 @@ public class PduPersister { default: throw new MmsException( "Unrecognized PDU type: " + Integer.toHexString(msgType)); + } + } finally { + synchronized(PDU_CACHE_INSTANCE) { + if (pdu != null) { + assert(PDU_CACHE_INSTANCE.get(uri) == null); + // Update the cache entry with the real info + cacheEntry = new PduCacheEntry(pdu, msgBox, threadId); + PDU_CACHE_INSTANCE.put(uri, cacheEntry); + } + PDU_CACHE_INSTANCE.setUpdating(uri, false); + PDU_CACHE_INSTANCE.notifyAll(); // tell anybody waiting on this entry to go ahead + } } - - synchronized(PDU_CACHE_INSTANCE ) { - assert(PDU_CACHE_INSTANCE.get(uri) == null); - // Update the cache entry with the real info - cacheEntry = new PduCacheEntry(pdu, msgBox, threadId); - PDU_CACHE_INSTANCE.put(uri, cacheEntry); - PDU_CACHE_INSTANCE.notifyAll(); // tell anybody waiting on this entry to go ahead - return pdu; - } + return pdu; } private void persistAddress( |
