Merge "Move flag for home launching from activity to task." into klp-dev
diff --git a/api/current.txt b/api/current.txt
index d31a38dc..739ef4c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -25018,9 +25018,7 @@
method public static void clearMetaKeyState(android.text.Editable, int);
method public long clearMetaKeyState(long, int);
method public static final int getMetaState(java.lang.CharSequence);
- method public static final int getMetaState(java.lang.CharSequence, android.view.KeyEvent);
method public static final int getMetaState(java.lang.CharSequence, int);
- method public static final int getMetaState(java.lang.CharSequence, int, android.view.KeyEvent);
method public static final int getMetaState(long);
method public static final int getMetaState(long, int);
method public static long handleKeyDown(long, int, android.view.KeyEvent);
@@ -30010,7 +30008,7 @@
method public deprecated void onConsoleMessage(java.lang.String, int, java.lang.String);
method public boolean onConsoleMessage(android.webkit.ConsoleMessage);
method public boolean onCreateWindow(android.webkit.WebView, boolean, boolean, android.os.Message);
- method public void onExceededDatabaseQuota(java.lang.String, java.lang.String, long, long, long, android.webkit.WebStorage.QuotaUpdater);
+ method public deprecated void onExceededDatabaseQuota(java.lang.String, java.lang.String, long, long, long, android.webkit.WebStorage.QuotaUpdater);
method public void onGeolocationPermissionsHidePrompt();
method public void onGeolocationPermissionsShowPrompt(java.lang.String, android.webkit.GeolocationPermissions.Callback);
method public void onHideCustomView();
@@ -30020,7 +30018,7 @@
method public boolean onJsPrompt(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String, android.webkit.JsPromptResult);
method public deprecated boolean onJsTimeout();
method public void onProgressChanged(android.webkit.WebView, int);
- method public void onReachedMaxAppCacheSize(long, long, android.webkit.WebStorage.QuotaUpdater);
+ method public deprecated void onReachedMaxAppCacheSize(long, long, android.webkit.WebStorage.QuotaUpdater);
method public void onReceivedIcon(android.webkit.WebView, android.graphics.Bitmap);
method public void onReceivedTitle(android.webkit.WebView, java.lang.String);
method public void onReceivedTouchIconUrl(android.webkit.WebView, java.lang.String, boolean);
@@ -30076,12 +30074,12 @@
method public int getCacheMode();
method public synchronized java.lang.String getCursiveFontFamily();
method public synchronized boolean getDatabaseEnabled();
- method public synchronized java.lang.String getDatabasePath();
+ method public deprecated synchronized java.lang.String getDatabasePath();
method public synchronized int getDefaultFixedFontSize();
method public synchronized int getDefaultFontSize();
method public synchronized java.lang.String getDefaultTextEncodingName();
method public static java.lang.String getDefaultUserAgent(android.content.Context);
- method public android.webkit.WebSettings.ZoomDensity getDefaultZoom();
+ method public deprecated android.webkit.WebSettings.ZoomDensity getDefaultZoom();
method public boolean getDisplayZoomControls();
method public synchronized boolean getDomStorageEnabled();
method public synchronized java.lang.String getFantasyFontFamily();
@@ -30118,11 +30116,11 @@
method public void setCacheMode(int);
method public synchronized void setCursiveFontFamily(java.lang.String);
method public synchronized void setDatabaseEnabled(boolean);
- method public synchronized void setDatabasePath(java.lang.String);
+ method public deprecated synchronized void setDatabasePath(java.lang.String);
method public synchronized void setDefaultFixedFontSize(int);
method public synchronized void setDefaultFontSize(int);
method public synchronized void setDefaultTextEncodingName(java.lang.String);
- method public void setDefaultZoom(android.webkit.WebSettings.ZoomDensity);
+ method public deprecated void setDefaultZoom(android.webkit.WebSettings.ZoomDensity);
method public void setDisplayZoomControls(boolean);
method public synchronized void setDomStorageEnabled(boolean);
method public deprecated void setEnableSmoothTransition(boolean);
@@ -30165,9 +30163,10 @@
public static final class WebSettings.LayoutAlgorithm extends java.lang.Enum {
method public static android.webkit.WebSettings.LayoutAlgorithm valueOf(java.lang.String);
method public static final android.webkit.WebSettings.LayoutAlgorithm[] values();
- enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm NARROW_COLUMNS;
+ enum_constant public static final deprecated android.webkit.WebSettings.LayoutAlgorithm NARROW_COLUMNS;
enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm NORMAL;
enum_constant public static final deprecated android.webkit.WebSettings.LayoutAlgorithm SINGLE_COLUMN;
+ enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm TEXT_AUTOSIZING;
}
public static final class WebSettings.PluginState extends java.lang.Enum {
@@ -30220,7 +30219,7 @@
method public long getUsage();
}
- public static abstract interface WebStorage.QuotaUpdater {
+ public static abstract deprecated interface WebStorage.QuotaUpdater {
method public abstract void updateQuota(long);
}
@@ -30248,7 +30247,7 @@
method public boolean canGoForward();
method public deprecated boolean canZoomIn();
method public deprecated boolean canZoomOut();
- method public android.graphics.Picture capturePicture();
+ method public deprecated android.graphics.Picture capturePicture();
method public void clearCache(boolean);
method public void clearFormData();
method public void clearHistory();
@@ -30265,7 +30264,7 @@
method public void findAllAsync(java.lang.String);
method public void findNext(boolean);
method public void flingScroll(int, int);
- method public void freeMemory();
+ method public deprecated void freeMemory();
method public android.net.http.SslCertificate getCertificate();
method public int getContentHeight();
method public android.graphics.Bitmap getFavicon();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index f250029..5618cab 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -2316,8 +2316,7 @@
}
@Override
- public void close() throws IOException {
- super.close();
+ public void releaseResources() {
if (!mProviderReleased) {
ContentResolver.this.releaseProvider(mContentProvider);
mProviderReleased = true;
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 40a3612..d0feaa3 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -255,6 +255,10 @@
return mRequiresDeviceUnlock;
}
+ public String getDescription() {
+ return mDescription;
+ }
+
public CharSequence loadLabel(PackageManager pm) {
return mService.loadLabel(pm);
}
@@ -287,6 +291,11 @@
Log.e(TAG, "AID " + aid + " is not correctly formatted.");
return false;
}
+ // Minimum AID length is 5 bytes, 10 hex chars
+ if (aidLength < 10) {
+ Log.e(TAG, "AID " + aid + " is shorter than 5 bytes.");
+ return false;
+ }
return true;
}
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 579971d..5a49b98 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -564,7 +564,11 @@
@Override
public void close() throws IOException {
if (mWrapped != null) {
- mWrapped.close();
+ try {
+ mWrapped.close();
+ } finally {
+ releaseResources();
+ }
} else {
closeWithStatus(Status.OK, null);
}
@@ -579,7 +583,11 @@
*/
public void closeWithError(String msg) throws IOException {
if (mWrapped != null) {
- mWrapped.closeWithError(msg);
+ try {
+ mWrapped.closeWithError(msg);
+ } finally {
+ releaseResources();
+ }
} else {
if (msg == null) {
throw new IllegalArgumentException("Message must not be null");
@@ -588,17 +596,22 @@
}
}
- private void closeWithStatus(int status, String msg) throws IOException {
- if (mWrapped != null) {
- mWrapped.closeWithStatus(status, msg);
- } else {
- if (mClosed) return;
- mClosed = true;
- mGuard.close();
- // Status MUST be sent before closing actual descriptor
- writeCommStatusAndClose(status, msg);
- IoUtils.closeQuietly(mFd);
- }
+ private void closeWithStatus(int status, String msg) {
+ if (mClosed) return;
+ mClosed = true;
+ mGuard.close();
+ // Status MUST be sent before closing actual descriptor
+ writeCommStatusAndClose(status, msg);
+ IoUtils.closeQuietly(mFd);
+ releaseResources();
+ }
+
+ /**
+ * Called when the fd is being closed, for subclasses to release any other resources
+ * associated with it, such as acquired providers.
+ * @hide
+ */
+ public void releaseResources() {
}
private byte[] getOrCreateStatusBuffer() {
@@ -793,6 +806,9 @@
@Override
protected void finalize() throws Throwable {
+ if (mWrapped != null) {
+ releaseResources();
+ }
if (mGuard != null) {
mGuard.warnIfOpen();
}
@@ -822,7 +838,11 @@
@Override
public void writeToParcel(Parcel out, int flags) {
if (mWrapped != null) {
- mWrapped.writeToParcel(out, flags);
+ try {
+ mWrapped.writeToParcel(out, flags);
+ } finally {
+ releaseResources();
+ }
} else {
out.writeFileDescriptor(mFd);
if (mCommFd != null) {
@@ -832,11 +852,8 @@
out.writeInt(0);
}
if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) {
- try {
- // Not a real close, so emit no status
- closeWithStatus(Status.SILENCE, null);
- } catch (IOException e) {
- }
+ // Not a real close, so emit no status
+ closeWithStatus(Status.SILENCE, null);
}
}
}
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index ba6f1d4..30bb447 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -56,7 +56,7 @@
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0
&& MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING, event) != 0) {
+ MetaKeyKeyListener.META_SELECTING) != 0) {
return widget.showContextMenu();
}
}
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 63607fa..4fede32 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -75,7 +75,7 @@
}
// Alt+Backspace or Alt+ForwardDelete deletes the current line, if possible.
- if (getMetaState(content, META_ALT_ON, event) == 1) {
+ if (event.isAltPressed() || getMetaState(content, META_ALT_ON) == 1) {
if (deleteLine(view, content)) {
return true;
}
diff --git a/core/java/android/text/method/BaseMovementMethod.java b/core/java/android/text/method/BaseMovementMethod.java
index 155a2c4..113a4be 100644
--- a/core/java/android/text/method/BaseMovementMethod.java
+++ b/core/java/android/text/method/BaseMovementMethod.java
@@ -135,7 +135,7 @@
*/
protected int getMovementMetaState(Spannable buffer, KeyEvent event) {
// We ignore locked modifiers and SHIFT.
- int metaState = MetaKeyKeyListener.getMetaState(buffer, event)
+ int metaState = (event.getMetaState() | MetaKeyKeyListener.getMetaState(buffer))
& ~(MetaKeyKeyListener.META_ALT_LOCKED | MetaKeyKeyListener.META_SYM_LOCKED);
return KeyEvent.normalizeMetaState(metaState) & ~KeyEvent.META_SHIFT_MASK;
}
diff --git a/core/java/android/text/method/DialerKeyListener.java b/core/java/android/text/method/DialerKeyListener.java
index bb8b0de..ce51fae 100644
--- a/core/java/android/text/method/DialerKeyListener.java
+++ b/core/java/android/text/method/DialerKeyListener.java
@@ -53,7 +53,7 @@
* from the KeyEvent.
*/
protected int lookup(KeyEvent event, Spannable content) {
- int meta = getMetaState(content, event);
+ int meta = event.getMetaState() | getMetaState(content);
int number = event.getNumber();
/*
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
index e9db5fd..5ebb957 100644
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ b/core/java/android/text/method/MetaKeyKeyListener.java
@@ -163,29 +163,6 @@
getActive(text, SELECTING, META_SELECTING, META_SELECTING);
}
- /**
- * Gets the state of the meta keys for a specific key event.
- *
- * For input devices that use toggled key modifiers, the `toggled' state
- * is stored into the text buffer. This method retrieves the meta state
- * for this event, accounting for the stored state. If the event has been
- * created by a device that does not support toggled key modifiers, like
- * a virtual device for example, the stored state is ignored.
- *
- * @param text the buffer in which the meta key would have been pressed.
- * @param event the event for which to evaluate the meta state.
- * @return an integer in which each bit set to one represents a pressed
- * or locked meta key.
- */
- public static final int getMetaState(final CharSequence text, final KeyEvent event) {
- int metaState = event.getMetaState();
- if (event.getKeyCharacterMap().getModifierBehavior()
- == KeyCharacterMap.MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED) {
- metaState |= getMetaState(text);
- }
- return metaState;
- }
-
// As META_SELECTING is @hide we should not mention it in public comments, hence the
// omission in @param meta
/**
@@ -215,37 +192,6 @@
}
}
- /**
- * Gets the state of a particular meta key to use with a particular key event.
- *
- * If the key event has been created by a device that does not support toggled
- * key modifiers, like a virtual keyboard for example, only the meta state in
- * the key event is considered.
- *
- * @param meta META_SHIFT_ON, META_ALT_ON, META_SYM_ON
- * @param text the buffer in which the meta key would have been pressed.
- * @param event the event for which to evaluate the meta state.
- * @return 0 if inactive, 1 if active, 2 if locked.
- */
- public static final int getMetaState(final CharSequence text, final int meta,
- final KeyEvent event) {
- int metaState = event.getMetaState();
- if (event.getKeyCharacterMap().getModifierBehavior()
- == KeyCharacterMap.MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED) {
- metaState |= getMetaState(text);
- }
- if (META_SELECTING == meta) {
- // #getMetaState(long, int) does not support META_SELECTING, but we want the same
- // behavior as #getMetaState(CharSequence, int) so we need to do it here
- if ((metaState & META_SELECTING) != 0) {
- // META_SELECTING is only ever set to PRESSED and can't be LOCKED, so return 1
- return 1;
- }
- return 0;
- }
- return getMetaState(metaState, meta);
- }
-
private static int getActive(CharSequence text, Object meta,
int on, int lock) {
if (!(text instanceof Spanned)) {
diff --git a/core/java/android/text/method/NumberKeyListener.java b/core/java/android/text/method/NumberKeyListener.java
index 988d566..5d4c732 100644
--- a/core/java/android/text/method/NumberKeyListener.java
+++ b/core/java/android/text/method/NumberKeyListener.java
@@ -41,7 +41,7 @@
protected abstract char[] getAcceptedChars();
protected int lookup(KeyEvent event, Spannable content) {
- return event.getMatch(getAcceptedChars(), getMetaState(content, event));
+ return event.getMatch(getAcceptedChars(), event.getMetaState() | getMetaState(content));
}
public CharSequence filter(CharSequence source, int start, int end,
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index 0bd46bc..98316ae 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -108,7 +108,7 @@
// QWERTY keyboard normal case
- int i = event.getUnicodeChar(getMetaState(content, event));
+ int i = event.getUnicodeChar(event.getMetaState() | getMetaState(content));
if (!mFullKeyboard) {
int count = event.getRepeatCount();
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java
index 4cc2c42..5f948bd 100644
--- a/core/java/android/transition/Fade.java
+++ b/core/java/android/transition/Fade.java
@@ -41,7 +41,6 @@
private static boolean DBG = Transition.DBG && false;
private static final String LOG_TAG = "Fade";
- private static final String PROPNAME_ALPHA = "android:fade:alpha";
private static final String PROPNAME_SCREEN_X = "android:fade:screenX";
private static final String PROPNAME_SCREEN_Y = "android:fade:screenY";
@@ -90,7 +89,8 @@
}
return null;
}
- final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", startAlpha, endAlpha);
+ final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "transitionAlpha", startAlpha,
+ endAlpha);
if (DBG) {
Log.d(LOG_TAG, "Created animator " + anim);
}
@@ -102,8 +102,6 @@
}
private void captureValues(TransitionValues transitionValues) {
- float alpha = transitionValues.view.getAlpha();
- transitionValues.values.put(PROPNAME_ALPHA, alpha);
int[] loc = new int[2];
transitionValues.view.getLocationOnScreen(loc);
transitionValues.values.put(PROPNAME_SCREEN_X, loc[0]);
@@ -116,29 +114,6 @@
captureValues(transitionValues);
}
-
- @Override
- public void captureEndValues(TransitionValues transitionValues) {
- super.captureEndValues(transitionValues);
- }
-
- @Override
- public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues) {
- Animator animator = super.createAnimator(sceneRoot, startValues, endValues);
- if (animator == null && startValues != null && endValues != null) {
- boolean endVisible = isVisible(endValues);
- final View endView = endValues.view;
- float endAlpha = endView.getAlpha();
- float startAlpha = (Float) startValues.values.get(PROPNAME_ALPHA);
- if ((endVisible && startAlpha < endAlpha && (mFadingMode & Fade.IN) != 0) ||
- (!endVisible && startAlpha > endAlpha && (mFadingMode & Fade.OUT) != 0)) {
- animator = createAnimation(endView, startAlpha, endAlpha, null);
- }
- }
- return animator;
- }
-
@Override
public Animator onAppear(ViewGroup sceneRoot,
TransitionValues startValues, int startVisibility,
@@ -152,40 +127,37 @@
Log.d(LOG_TAG, "Fade.onAppear: startView, startVis, endView, endVis = " +
startView + ", " + startVisibility + ", " + endView + ", " + endVisibility);
}
- // if alpha < 1, just fade it in from the current value
- if (endView.getAlpha() == 1.0f) {
- endView.setAlpha(0);
- TransitionListener transitionListener = new TransitionListenerAdapter() {
- boolean mCanceled = false;
- float mPausedAlpha;
+ endView.setTransitionAlpha(0);
+ TransitionListener transitionListener = new TransitionListenerAdapter() {
+ boolean mCanceled = false;
+ float mPausedAlpha;
- @Override
- public void onTransitionCancel(Transition transition) {
- endView.setAlpha(1);
- mCanceled = true;
- }
+ @Override
+ public void onTransitionCancel(Transition transition) {
+ endView.setTransitionAlpha(1);
+ mCanceled = true;
+ }
- @Override
- public void onTransitionEnd(Transition transition) {
- if (!mCanceled) {
- endView.setAlpha(1);
- }
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ if (!mCanceled) {
+ endView.setTransitionAlpha(1);
}
+ }
- @Override
- public void onTransitionPause(Transition transition) {
- mPausedAlpha = endView.getAlpha();
- endView.setAlpha(1);
- }
+ @Override
+ public void onTransitionPause(Transition transition) {
+ mPausedAlpha = endView.getTransitionAlpha();
+ endView.setTransitionAlpha(1);
+ }
- @Override
- public void onTransitionResume(Transition transition) {
- endView.setAlpha(mPausedAlpha);
- }
- };
- addListener(transitionListener);
- }
- return createAnimation(endView, endView.getAlpha(), 1, null);
+ @Override
+ public void onTransitionResume(Transition transition) {
+ endView.setTransitionAlpha(mPausedAlpha);
+ }
+ };
+ addListener(transitionListener);
+ return createAnimation(endView, 0, 1, null);
}
@Override
@@ -236,7 +208,7 @@
overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
sceneRoot.getOverlay().add(overlayView);
// TODO: add automatic facility to Visibility superclass for keeping views around
- final float startAlpha = view.getAlpha();
+ final float startAlpha = 1;
float endAlpha = 0;
final View finalView = view;
final View finalOverlayView = overlayView;
@@ -245,7 +217,7 @@
final AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- finalView.setAlpha(startAlpha);
+ finalView.setTransitionAlpha(startAlpha);
// TODO: restore view offset from overlay repositioning
if (finalViewToKeep != null) {
finalViewToKeep.setVisibility(finalVisibility);
@@ -276,7 +248,7 @@
// VISIBLE for the duration of the transition
viewToKeep.setVisibility((View.VISIBLE));
// TODO: add automatic facility to Visibility superclass for keeping views around
- final float startAlpha = view.getAlpha();
+ final float startAlpha = 1;
float endAlpha = 0;
final View finalView = view;
final View finalOverlayView = overlayView;
@@ -291,8 +263,8 @@
if (finalViewToKeep != null && !mCanceled) {
finalViewToKeep.setVisibility(finalVisibility);
}
- mPausedAlpha = finalView.getAlpha();
- finalView.setAlpha(startAlpha);
+ mPausedAlpha = finalView.getTransitionAlpha();
+ finalView.setTransitionAlpha(startAlpha);
}
@Override
@@ -300,21 +272,21 @@
if (finalViewToKeep != null && !mCanceled) {
finalViewToKeep.setVisibility(View.VISIBLE);
}
- finalView.setAlpha(mPausedAlpha);
+ finalView.setTransitionAlpha(mPausedAlpha);
}
@Override
public void onAnimationCancel(Animator animation) {
mCanceled = true;
if (mPausedAlpha >= 0) {
- finalView.setAlpha(mPausedAlpha);
+ finalView.setTransitionAlpha(mPausedAlpha);
}
}
@Override
public void onAnimationEnd(Animator animation) {
if (!mCanceled) {
- finalView.setAlpha(startAlpha);
+ finalView.setTransitionAlpha(startAlpha);
}
// TODO: restore view offset from overlay repositioning
if (finalViewToKeep != null && !mCanceled) {
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 60b4708..4a99153 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -353,7 +353,7 @@
if (endValues.viewValues.get(view) != null) {
end = endValues.viewValues.get(view);
endCopy.remove(view);
- } else {
+ } else if (id != View.NO_ID) {
end = endValues.idValues.get(id);
View removeView = null;
for (View viewToRemove : endCopy.keySet()) {
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index f72b36e..6fdd309 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -354,7 +354,7 @@
clone.mTransitions = new ArrayList<Transition>();
int numTransitions = mTransitions.size();
for (int i = 0; i < numTransitions; ++i) {
- clone.mTransitions.add((Transition) mTransitions.get(i).clone());
+ clone.addTransition((Transition) mTransitions.get(i).clone());
}
return clone;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a5db6ee..4680e76 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2894,6 +2894,13 @@
*/
@ViewDebug.ExportedProperty
float mAlpha = 1f;
+
+ /**
+ * The opacity of the view as manipulated by the Fade transition. This is a hidden
+ * property only used by transitions, which is composited with the other alpha
+ * values to calculate the final visual alpha value.
+ */
+ float mTransitionAlpha = 1f;
}
TransformationInfo mTransformationInfo;
@@ -5335,7 +5342,8 @@
View view = (View) current;
// We have attach info so this view is attached and there is no
// need to check whether we reach to ViewRootImpl on the way up.
- if (view.getAlpha() <= 0 || view.getVisibility() != VISIBLE) {
+ if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
+ view.getVisibility() != VISIBLE) {
return false;
}
current = view.mParent;
@@ -9786,7 +9794,7 @@
mPrivateFlags &= ~PFLAG_ALPHA_SET;
invalidateViewProperty(true, false);
if (mDisplayList != null) {
- mDisplayList.setAlpha(alpha);
+ mDisplayList.setAlpha(getFinalAlpha());
}
}
}
@@ -9813,7 +9821,7 @@
} else {
mPrivateFlags &= ~PFLAG_ALPHA_SET;
if (mDisplayList != null) {
- mDisplayList.setAlpha(alpha);
+ mDisplayList.setAlpha(getFinalAlpha());
}
}
}
@@ -9821,6 +9829,51 @@
}
/**
+ * This property is hidden and intended only for use by the Fade transition, which
+ * animates it to produce a visual translucency that does not side-effect (or get
+ * affected by) the real alpha property. This value is composited with the other
+ * alpha value (and the AlphaAnimation value, when that is present) to produce
+ * a final visual translucency result, which is what is passed into the DisplayList.
+ *
+ * @hide
+ */
+ public void setTransitionAlpha(float alpha) {
+ ensureTransformationInfo();
+ if (mTransformationInfo.mTransitionAlpha != alpha) {
+ mTransformationInfo.mTransitionAlpha = alpha;
+ mPrivateFlags &= ~PFLAG_ALPHA_SET;
+ invalidateViewProperty(true, false);
+ if (mDisplayList != null) {
+ mDisplayList.setAlpha(getFinalAlpha());
+ }
+ }
+ }
+
+ /**
+ * Calculates the visual alpha of this view, which is a combination of the actual
+ * alpha value and the transitionAlpha value (if set).
+ */
+ private float getFinalAlpha() {
+ if (mTransformationInfo != null) {
+ return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
+ }
+ return 1;
+ }
+
+ /**
+ * This property is hidden and intended only for use by the Fade transition, which
+ * animates it to produce a visual translucency that does not side-effect (or get
+ * affected by) the real alpha property. This value is composited with the other
+ * alpha value (and the AlphaAnimation value, when that is present) to produce
+ * a final visual translucency result, which is what is passed into the DisplayList.
+ *
+ * @hide
+ */
+ public float getTransitionAlpha() {
+ return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
+ }
+
+ /**
* Top position of this view relative to its parent.
*
* @return The top of this view, in pixels.
@@ -10913,7 +10966,7 @@
@ViewDebug.ExportedProperty(category = "drawing")
public boolean isOpaque() {
return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
- ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
+ getFinalAlpha() >= 1.0f;
}
/**
@@ -13868,7 +13921,7 @@
}
}
if (mTransformationInfo != null) {
- alpha *= mTransformationInfo.mAlpha;
+ alpha *= getFinalAlpha();
if (alpha < 1) {
final int multipliedAlpha = (int) (255 * alpha);
if (onSetAlpha(multipliedAlpha)) {
@@ -14057,8 +14110,8 @@
}
}
- float alpha = useDisplayListProperties ? 1 : getAlpha();
- if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
+ float alpha = useDisplayListProperties ? 1 : (getAlpha() * getTransitionAlpha());
+ if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
(mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
if (transformToApply != null || !childHasIdentityMatrix) {
int transX = 0;
@@ -14115,7 +14168,7 @@
layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
}
if (useDisplayListProperties) {
- displayList.setAlpha(alpha * getAlpha());
+ displayList.setAlpha(alpha * getAlpha() * getTransitionAlpha());
} else if (layerType == LAYER_TYPE_NONE) {
final int scrollX = hasDisplayList ? 0 : sx;
final int scrollY = hasDisplayList ? 0 : sy;
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index ad8b51d..f9298ea 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -990,10 +990,10 @@
mStart = false;
if (mDataCopy != null) {
mData = mDataCopy;
+ mAccess.mData.clear();
+ mAccess.mSize = 0;
}
mDataCopy = null;
- mAccess.mData.clear();
- mAccess.mSize = 0;
}
int size() {
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 21b0578..aa57423 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -238,9 +238,10 @@
* @param totalQuota The total quota for all origins, in bytes
* @param quotaUpdater An instance of {@link WebStorage.QuotaUpdater} which
* must be used to inform the WebView of the new quota.
+ * @deprecated This method is no longer called; WebView now uses the HTML5 / JavaScript Quota
+ * Management API.
*/
- // Note that the callback must always be executed at some point to ensure
- // that the sleeping WebCore thread is woken up.
+ @Deprecated
public void onExceededDatabaseQuota(String url, String databaseIdentifier,
long quota, long estimatedDatabaseSize, long totalQuota,
WebStorage.QuotaUpdater quotaUpdater) {
@@ -263,9 +264,10 @@
* @param quota the current maximum Application Cache size, in bytes
* @param quotaUpdater An instance of {@link WebStorage.QuotaUpdater} which
* must be used to inform the WebView of the new quota.
+ * @deprecated This method is no longer called; WebView now uses the HTML5 / JavaScript Quota
+ * Management API.
*/
- // Note that the callback must always be executed at some point to ensure
- // that the sleeping WebCore thread is woken up.
+ @Deprecated
public void onReachedMaxAppCacheSize(long requiredStorage, long quota,
WebStorage.QuotaUpdater quotaUpdater) {
quotaUpdater.updateQuota(quota);
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 7a38a16..98ef66e 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -33,14 +33,17 @@
/**
* Enum for controlling the layout of html.
* <ul>
- * <li>NORMAL means no rendering changes.</li>
+ * <li>NORMAL means no rendering changes. This is the recommended choice for maximum
+ * compatibility across different platforms and Android versions.</li>
* <li>SINGLE_COLUMN moves all content into one column that is the width of the
* view.</li>
- * <li>NARROW_COLUMNS makes all columns no wider than the screen if possible.</li>
+ * <li>NARROW_COLUMNS makes all columns no wider than the screen if possible. Only use
+ * this for API levels prior to {@link android.os.Build.VERSION_CODES#KITKAT}.</li>
* <li>TEXT_AUTOSIZING boosts font size of paragraphs based on heuristics to make
* the text readable when viewing a wide-viewport layout in the overview mode.
* It is recommended to enable zoom support {@link #setSupportZoom} when
- * using this mode.</li>
+ * using this mode. Supported from API level
+ * {@link android.os.Build.VERSION_CODES#KITKAT}</li>
* </ul>
*/
// XXX: These must match LayoutAlgorithm in Settings.h in WebCore.
@@ -51,10 +54,11 @@
*/
@Deprecated
SINGLE_COLUMN,
- NARROW_COLUMNS,
/**
- * @hide
+ * @deprecated This algorithm is now obsolete.
*/
+ @Deprecated
+ NARROW_COLUMNS,
TEXT_AUTOSIZING
}
@@ -510,7 +514,10 @@
* and {@link #setUseWideViewPort} can be used.
*
* @param zoom the zoom density
+ * @deprecated This method is no longer supported, see the function documentation for
+ * recommended alternatives.
*/
+ @Deprecated
public void setDefaultZoom(ZoomDensity zoom) {
throw new MustOverrideException();
}
@@ -523,6 +530,7 @@
*
* @return the zoom density
* @see #setDefaultZoom
+ * @deprecated Will only return the default value.
*/
public ZoomDensity getDefaultZoom() {
throw new MustOverrideException();
@@ -1059,10 +1067,13 @@
*
* @param databasePath a path to the directory where databases should be
* saved.
+ * @deprecated Database paths are managed by the implementation and calling this method
+ * will have no effect.
*/
// This will update WebCore when the Sync runs in the C++ side.
// Note that the WebCore Database Tracker only allows the path to be set
// once.
+ @Deprecated
public synchronized void setDatabasePath(String databasePath) {
throw new MustOverrideException();
}
@@ -1161,7 +1172,9 @@
*
* @return the String path to the database storage API databases
* @see #setDatabasePath
+ * @deprecated Database paths are managed by the implementation this method is obsolete.
*/
+ @Deprecated
public synchronized String getDatabasePath() {
throw new MustOverrideException();
}
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index 7d9373c..3bfe9cf 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -41,12 +41,9 @@
* See
* {@link WebChromeClient#onExceededDatabaseQuota} and
* {@link WebChromeClient#onReachedMaxAppCacheSize}.
+ * @deprecated This class is obsolete and no longer used.
*/
- // We primarily want this to allow us to call back the sleeping WebCore
- // thread from outside the WebViewCore class (as the native call is
- // private). It is imperative that the setDatabaseQuota method is
- // executed after a decision to either allow or deny new quota is made,
- // otherwise the WebCore thread will remain asleep.
+ @Deprecated
public interface QuotaUpdater {
/**
* Provides a new quota, specified in bytes.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 15331dc..d05bba7 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1058,9 +1058,20 @@
* {@link android.os.Build.VERSION_CODES#HONEYCOMB} and
* {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH} inclusive, the
* picture does not include fixed position elements or scrollable divs.
+ * <p>
+ * Note that from {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} the returned picture
+ * should only be drawn into bitmap-backed Canvas - using any other type of Canvas will involve
+ * additional conversion at a cost in memory and performance. Also the
+ * {@link android.graphics.Picture#createFromStream} and
+ * {@link android.graphics.Picture#writeToStream} methods are not supported on the
+ * returned object.
+ *
+ * @deprecated Use {@link #onDraw} to obtain a bitmap snapshot of the WebView, or
+ * {@link #saveWebArchive} or {@link #exportToPdf} to save the content to a file.
*
* @return a picture that captures the current contents of this WebView
*/
+ @Deprecated
public Picture capturePicture() {
checkThread();
if (DebugFlags.TRACE_API) Log.d(LOGTAG, "capturePicture");
@@ -1342,7 +1353,10 @@
/**
* Informs this WebView that memory is low so that it can free any available
* memory.
+ * @deprecated Memory caches are automatically dropped when no longer needed, and in response
+ * to system memory pressure.
*/
+ @Deprecated
public void freeMemory() {
checkThread();
if (DebugFlags.TRACE_API) Log.d(LOGTAG, "freeMemory");
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index f9bb233..9c20de2 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -3,6 +3,7 @@
#include "BitmapFactory.h"
#include "NinePatchPeeker.h"
#include "SkData.h"
+#include "SkFrontBufferedStream.h"
#include "SkImageDecoder.h"
#include "SkImageRef_ashmem.h"
#include "SkImageRef_GlobalPool.h"
@@ -120,7 +121,7 @@
}
}
-static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream,
+static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStreamRewindable* stream,
int sampleSize, bool ditherImage) {
SkImageRef* pr;
@@ -465,13 +466,17 @@
jobject padding, jobject options) {
jobject bitmap = NULL;
- SkAutoTUnref<SkStreamRewindable> stream(GetRewindableStream(env, is, storage));
+ SkAutoTUnref<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage));
if (stream.get()) {
+ // Need to buffer enough input to be able to rewind as much as might be read by a decoder
+ // trying to determine the stream's format. Currently the most is 64, read by
+ // SkImageDecoder_libwebp.
+ // FIXME: Get this number from SkImageDecoder
+ SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(stream, 64));
+ SkASSERT(bufferedStream.get() != NULL);
// for now we don't allow purgeable with java inputstreams
- // FIXME: GetRewindableStream may have made a copy, in which case
- // purgeable should be allowed.
- bitmap = doDecode(env, stream, padding, options, false, false);
+ bitmap = doDecode(env, bufferedStream, padding, options, false, false);
}
return bitmap;
}
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index f773f59..da8f083 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -5,18 +5,12 @@
#include "SkStream.h"
#include "SkTypes.h"
#include "Utils.h"
-#include <androidfw/Asset.h>
-static jmethodID gInputStream_resetMethodID;
-static jmethodID gInputStream_markMethodID;
-static jmethodID gInputStream_markSupportedMethodID;
static jmethodID gInputStream_readMethodID;
static jmethodID gInputStream_skipMethodID;
-class RewindableJavaStream;
-
/**
- * Non-rewindable wrapper for a Java InputStream.
+ * Wrapper for a Java InputStream.
*/
class JavaInputStreamAdaptor : public SkStream {
public:
@@ -64,25 +58,6 @@
}
private:
- // Does not override rewind, since a JavaInputStreamAdaptor's interface
- // does not support rewinding. RewindableJavaStream, which is a friend,
- // will be able to call this method to rewind.
- bool doRewind() {
- JNIEnv* env = fEnv;
-
- fBytesRead = 0;
- fIsAtEnd = false;
-
- env->CallVoidMethod(fJavaInputStream, gInputStream_resetMethodID);
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- SkDebugf("------- reset threw an exception\n");
- return false;
- }
- return true;
- }
-
size_t doRead(void* buffer, size_t size) {
JNIEnv* env = fEnv;
size_t bytesRead = 0;
@@ -148,9 +123,6 @@
size_t fCapacity;
size_t fBytesRead;
bool fIsAtEnd;
-
- // Allows access to doRewind and fBytesRead.
- friend class RewindableJavaStream;
};
SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
@@ -190,123 +162,6 @@
return adaptor_to_mem_stream(adaptor.get());
}
-/**
- * Wrapper for a Java InputStream which is rewindable and
- * has a length.
- */
-class RewindableJavaStream : public SkStreamRewindable {
-public:
- // RewindableJavaStream takes ownership of adaptor.
- RewindableJavaStream(JavaInputStreamAdaptor* adaptor, size_t length)
- : fAdaptor(adaptor)
- , fLength(length) {
- SkASSERT(fAdaptor != NULL);
- }
-
- virtual ~RewindableJavaStream() {
- fAdaptor->unref();
- }
-
- virtual bool rewind() {
- return fAdaptor->doRewind();
- }
-
- virtual size_t read(void* buffer, size_t size) {
- return fAdaptor->read(buffer, size);
- }
-
- virtual bool isAtEnd() const {
- return fAdaptor->isAtEnd();
- }
-
- virtual size_t getLength() const {
- return fLength;
- }
-
- virtual bool hasLength() const {
- return true;
- }
-
- virtual SkStreamRewindable* duplicate() const {
- // Duplicating this stream requires rewinding and
- // reading, which modify this Stream (and could
- // fail, leaving this one invalid).
- SkASSERT(false);
- return NULL;
- }
-
-private:
- JavaInputStreamAdaptor* fAdaptor;
- const size_t fLength;
-};
-
-static jclass gByteArrayInputStream_Clazz;
-static jfieldID gCountField;
-static jfieldID gPosField;
-
-/**
- * If jstream is a ByteArrayInputStream, return its remaining length. Otherwise
- * return 0.
- */
-static size_t get_length_from_byte_array_stream(JNIEnv* env, jobject jstream) {
- if (env->IsInstanceOf(jstream, gByteArrayInputStream_Clazz)) {
- // Return the remaining length, to keep the same behavior of using the rest of the
- // stream.
- return env->GetIntField(jstream, gCountField) - env->GetIntField(jstream, gPosField);
- }
- return 0;
-}
-
-/**
- * If jstream is a class that has a length, return it. Otherwise
- * return 0.
- * Only checks for a set of subclasses.
- */
-static size_t get_length_if_supported(JNIEnv* env, jobject jstream) {
- size_t len = get_length_from_byte_array_stream(env, jstream);
- if (len > 0) {
- return len;
- }
- return 0;
-}
-
-SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream,
- jbyteArray storage) {
- SkAutoTUnref<SkStream> adaptor(CreateJavaInputStreamAdaptor(env, stream, storage));
- if (NULL == adaptor.get()) {
- return NULL;
- }
-
- const size_t length = get_length_if_supported(env, stream);
- if (length > 0 && env->CallBooleanMethod(stream, gInputStream_markSupportedMethodID)) {
- // Set the readLimit for mark to the end of the stream, so it can
- // be rewound regardless of how much has been read.
- env->CallVoidMethod(stream, gInputStream_markMethodID, length);
- // RewindableJavaStream will unref adaptor when it is destroyed.
- return new RewindableJavaStream(static_cast<JavaInputStreamAdaptor*>(adaptor.detach()),
- length);
- }
-
- return adaptor_to_mem_stream(adaptor.get());
-}
-
-static jclass gAssetInputStream_Clazz;
-static jmethodID gGetAssetIntMethodID;
-
-android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject jstream) {
- if (!env->IsInstanceOf(jstream, gAssetInputStream_Clazz)) {
- return NULL;
- }
-
- jint jasset = env->CallIntMethod(jstream, gGetAssetIntMethodID);
- android::Asset* a = reinterpret_cast<android::Asset*>(jasset);
- if (NULL == a) {
- jniThrowNullPointerException(env, "NULL native asset");
- return NULL;
- }
- return new android::AssetStreamAdaptor(a);
-}
-
///////////////////////////////////////////////////////////////////////////////
static jmethodID gOutputStream_writeMethodID;
@@ -382,13 +237,6 @@
return clazz;
}
-static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
- const char fieldname[], const char type[]) {
- jfieldID id = env->GetFieldID(clazz, fieldname, type);
- SkASSERT(!env->ExceptionCheck());
- return id;
-}
-
static jmethodID getMethodIDCheck(JNIEnv* env, jclass clazz,
const char methodname[], const char type[]) {
jmethodID id = env->GetMethodID(clazz, methodname, type);
@@ -398,25 +246,9 @@
int register_android_graphics_CreateJavaOutputStreamAdaptor(JNIEnv* env) {
jclass inputStream_Clazz = findClassCheck(env, "java/io/InputStream");
- gInputStream_resetMethodID = getMethodIDCheck(env, inputStream_Clazz, "reset", "()V");
- gInputStream_markMethodID = getMethodIDCheck(env, inputStream_Clazz, "mark", "(I)V");
- gInputStream_markSupportedMethodID = getMethodIDCheck(env, inputStream_Clazz, "markSupported", "()Z");
gInputStream_readMethodID = getMethodIDCheck(env, inputStream_Clazz, "read", "([BII)I");
gInputStream_skipMethodID = getMethodIDCheck(env, inputStream_Clazz, "skip", "(J)J");
- gByteArrayInputStream_Clazz = findClassCheck(env, "java/io/ByteArrayInputStream");
- // Ref gByteArrayInputStream_Clazz so we can continue to refer to it when
- // calling IsInstance.
- gByteArrayInputStream_Clazz = (jclass) env->NewGlobalRef(gByteArrayInputStream_Clazz);
- gCountField = getFieldIDCheck(env, gByteArrayInputStream_Clazz, "count", "I");
- gPosField = getFieldIDCheck(env, gByteArrayInputStream_Clazz, "pos", "I");
-
- gAssetInputStream_Clazz = findClassCheck(env, "android/content/res/AssetManager$AssetInputStream");
- // Ref gAssetInputStream_Clazz so we can continue to refer to it when
- // calling IsInstance.
- gAssetInputStream_Clazz = (jclass) env->NewGlobalRef(gAssetInputStream_Clazz);
- gGetAssetIntMethodID = getMethodIDCheck(env, gAssetInputStream_Clazz, "getAssetInt", "()I");
-
jclass outputStream_Clazz = findClassCheck(env, "java/io/OutputStream");
gOutputStream_writeMethodID = getMethodIDCheck(env, outputStream_Clazz, "write", "([BII)V");
gOutputStream_flushMethodID = getMethodIDCheck(env, outputStream_Clazz, "flush", "()V");
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
index fcc0c9a..ecd270f 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
@@ -4,10 +4,6 @@
//#include <android_runtime/AndroidRuntime.h>
#include "jni.h"
-namespace android {
- class AssetStreamAdaptor;
-}
-
class SkMemoryStream;
class SkStream;
class SkStreamRewindable;
@@ -15,6 +11,7 @@
/**
* Return an adaptor from a Java InputStream to an SkStream.
+ * Does not support rewind.
* @param env JNIEnv object.
* @param stream Pointer to Java InputStream.
* @param storage Java byte array for retrieving data from the
@@ -28,7 +25,7 @@
jbyteArray storage);
/**
- * Copy a Java InputStream.
+ * Copy a Java InputStream. The result will be rewindable.
* @param env JNIEnv object.
* @param stream Pointer to Java InputStream.
* @param storage Java byte array for retrieving data from the
@@ -39,32 +36,6 @@
SkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream,
jbyteArray storage);
-/**
- * Get a rewindable stream from a Java InputStream.
- * @param env JNIEnv object.
- * @param stream Pointer to Java InputStream.
- * @param storage Java byte array for retrieving data from the
- * Java InputStream.
- * @return SkStreamRewindable Either a wrapper around the Java
- * InputStream, if possible, or a copy which is rewindable.
- * Since it may be a wrapper, must not be used after the
- * caller returns, like the result of CreateJavaInputStreamAdaptor.
- */
-SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream,
- jbyteArray storage);
-
-/**
- * If the Java InputStream is an AssetInputStream, return an adaptor.
- * This should not be used after the calling function returns, since
- * the caller may close the asset. Returns NULL if the stream is
- * not an AssetInputStream.
- * @param env JNIEnv object.
- * @param stream Pointer to Java InputStream.
- * @return AssetStreamAdaptor representing the InputStream, or NULL.
- * Must not be held onto.
- */
-android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject stream);
-
SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
jbyteArray storage);
#endif
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index 2eae841..feb2dec 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -1,4 +1,5 @@
#include "ScopedLocalRef.h"
+#include "SkFrontBufferedStream.h"
#include "SkMovie.h"
#include "SkStream.h"
#include "GraphicsJNI.h"
@@ -81,23 +82,33 @@
c->drawBitmap(b, sx, sy, p);
}
+static jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jint native_asset) {
+ android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset);
+ if (asset == NULL) return NULL;
+ SkAutoTUnref<SkStreamRewindable> stream (new android::AssetStreamAdaptor(asset));
+ SkMovie* moov = SkMovie::DecodeStream(stream.get());
+ return create_jmovie(env, moov);
+}
+
static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) {
NPE_CHECK_RETURN_ZERO(env, istream);
- SkStreamRewindable* strm = CheckForAssetStream(env, istream);
- jbyteArray byteArray = NULL;
- ScopedLocalRef<jbyteArray> scoper(env, NULL);
- if (NULL == strm) {
- byteArray = env->NewByteArray(16*1024);
- scoper.reset(byteArray);
- strm = GetRewindableStream(env, istream, byteArray);
- }
+ jbyteArray byteArray = env->NewByteArray(16*1024);
+ ScopedLocalRef<jbyteArray> scoper(env, byteArray);
+ SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray);
if (NULL == strm) {
return 0;
}
- SkMovie* moov = SkMovie::DecodeStream(strm);
+ // Need to buffer enough input to be able to rewind as much as might be read by a decoder
+ // trying to determine the stream's format. The only decoder for movies is GIF, which
+ // will only read 6.
+ // FIXME: Get this number from SkImageDecoder
+ SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6));
+ SkASSERT(bufferedStream.get() != NULL);
+
+ SkMovie* moov = SkMovie::DecodeStream(bufferedStream);
strm->unref();
return create_jmovie(env, moov);
}
@@ -135,7 +146,9 @@
{ "setTime", "(I)Z", (void*)movie_setTime },
{ "draw", "(Landroid/graphics/Canvas;FFLandroid/graphics/Paint;)V",
(void*)movie_draw },
- { "decodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;",
+ { "nativeDecodeAsset", "(I)Landroid/graphics/Movie;",
+ (void*)movie_decodeAsset },
+ { "nativeDecodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;",
(void*)movie_decodeStream },
{ "nativeDestructor","(I)V", (void*)movie_destructor },
{ "decodeByteArray", "([BII)Landroid/graphics/Movie;",
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 23606a1..c8ace44 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -569,10 +569,7 @@
final int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
bm = nativeDecodeAsset(asset, outPadding, opts);
} else {
- byte [] tempStorage = null;
- if (opts != null) tempStorage = opts.inTempStorage;
- if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
- bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
+ bm = decodeStreamInternal(is, outPadding, opts);
}
if (bm == null && opts != null && opts.inBitmap != null) {
@@ -588,6 +585,18 @@
}
/**
+ * Private helper function for decoding an InputStream natively. Buffers the input enough to
+ * do a rewind as needed, and supplies temporary storage if necessary. is MUST NOT be null.
+ */
+ private static Bitmap decodeStreamInternal(InputStream is, Rect outPadding, Options opts) {
+ // ASSERT(is != null);
+ byte [] tempStorage = null;
+ if (opts != null) tempStorage = opts.inTempStorage;
+ if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
+ return nativeDecodeStream(is, tempStorage, outPadding, opts);
+ }
+
+ /**
* Decode an input stream into a bitmap. If the input stream is null, or
* cannot be used to decode a bitmap, the function returns null.
* The stream's position will be where ever it was after the encoded data
@@ -624,13 +633,8 @@
bm = nativeDecodeFileDescriptor(fd, outPadding, opts);
} else {
FileInputStream fis = new FileInputStream(fd);
- // FIXME: If nativeDecodeStream grabbed the pointer to tempStorage
- // from Options, this code would not need to be duplicated.
- byte [] tempStorage = null;
- if (opts != null) tempStorage = opts.inTempStorage;
- if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
try {
- bm = nativeDecodeStream(fis, tempStorage, outPadding, opts);
+ bm = decodeStreamInternal(fis, outPadding, opts);
} finally {
try {
fis.close();
diff --git a/graphics/java/android/graphics/Movie.java b/graphics/java/android/graphics/Movie.java
index 4a33453..9419faf 100644
--- a/graphics/java/android/graphics/Movie.java
+++ b/graphics/java/android/graphics/Movie.java
@@ -16,12 +16,13 @@
package android.graphics;
+import android.content.res.AssetManager;
import java.io.InputStream;
import java.io.FileInputStream;
public class Movie {
private final int mNativeMovie;
-
+
private Movie(int nativeMovie) {
if (nativeMovie == 0) {
throw new RuntimeException("native movie creation failed");
@@ -42,7 +43,20 @@
draw(canvas, x, y, null);
}
- public static native Movie decodeStream(InputStream is);
+ public static Movie decodeStream(InputStream is) {
+ if (is == null) {
+ return null;
+ }
+ if (is instanceof AssetManager.AssetInputStream) {
+ final int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+ return nativeDecodeAsset(asset);
+ }
+
+ return nativeDecodeStream(is);
+ }
+
+ private static native Movie nativeDecodeAsset(int asset);
+ private static native Movie nativeDecodeStream(InputStream is);
public static native Movie decodeByteArray(byte[] data, int offset,
int length);
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index f9e48d4..1bd32c4 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -83,7 +83,8 @@
* @param format
* The format of the Image that this reader will produce. This
* must be one of the {@link android.graphics.ImageFormat} or
- * {@link android.graphics.PixelFormat} constants.
+ * {@link android.graphics.PixelFormat} constants. Note that
+ * not all formats is supported, like ImageFormat.NV21.
* @param maxImages
* The maximum number of images the user will want to
* access simultaneously. This should be as small as possible to limit
@@ -116,6 +117,11 @@
"Maximum outstanding image count must be at least 1");
}
+ if (format == ImageFormat.NV21) {
+ throw new IllegalArgumentException(
+ "NV21 format is not supported");
+ }
+
mNumPlanes = getNumPlanesFromFormat();
nativeInit(new WeakReference<ImageReader>(this), width, height, format, maxImages);
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index a03dbf3..0030dbd 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -721,13 +721,18 @@
return ACQUIRE_NO_BUFFERS;
}
+ if (buffer->format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+ jniThrowException(env, "java/lang/UnsupportedOperationException",
+ "NV21 format is not supported by ImageReader");
+ return -1;
+ }
+
// Check if the left-top corner of the crop rect is origin, we currently assume this point is
// zero, will revist this once this assumption turns out problematic.
Point lt = buffer->crop.leftTop();
if (lt.x != 0 || lt.y != 0) {
- ALOGE("crop left: %d, top = %d", lt.x, lt.y);
- jniThrowException(env, "java/lang/UnsupportedOperationException",
- "crop left top corner need to at origin");
+ jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+ "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y);
return -1;
}