summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml24
-rw-r--r--cmds/dumpstate/dumpstate.c9
-rw-r--r--core/java/android/text/CharSequenceIterator.java95
-rw-r--r--core/java/android/text/Selection.java49
-rw-r--r--core/java/android/text/method/ArrowKeyMovementMethod.java125
-rw-r--r--core/java/android/text/method/BaseMovementMethod.java22
-rw-r--r--core/java/android/view/View.java40
-rw-r--r--core/java/android/view/ViewGroup.java27
-rw-r--r--core/java/android/webkit/HTML5VideoView.java8
-rw-r--r--core/java/android/webkit/HTML5VideoViewProxy.java28
-rw-r--r--core/jni/android_bluetooth_HeadsetBase.cpp30
-rw-r--r--core/jni/android_opengl_GLES11.cpp61
-rw-r--r--core/jni/android_opengl_GLES11Ext.cpp414
-rw-r--r--core/jni/android_opengl_GLES20.cpp80
-rwxr-xr-xcore/res/res/values/attrs.xml12
-rw-r--r--core/res/res/values/public.xml2
-rwxr-xr-xdocs/html/guide/market/billing/billing_about.jd62
-rwxr-xr-xdocs/html/guide/market/billing/billing_admin.jd20
-rwxr-xr-xdocs/html/guide/market/billing/billing_best_practices.jd6
-rwxr-xr-xdocs/html/guide/market/billing/billing_integrate.jd21
-rwxr-xr-xdocs/html/guide/market/billing/billing_overview.jd16
-rwxr-xr-xdocs/html/guide/market/billing/billing_reference.jd10
-rwxr-xr-xdocs/html/guide/market/billing/billing_testing.jd6
-rwxr-xr-xdocs/html/guide/market/billing/index.jd10
-rwxr-xr-xdocs/html/images/billing_list_form.pngbin108532 -> 96595 bytes
-rwxr-xr-xdocs/html/images/billing_product_list.pngbin86319 -> 55100 bytes
-rwxr-xr-xdocs/html/images/billing_product_list_entry.pngbin78147 -> 77842 bytes
-rw-r--r--graphics/java/android/graphics/YuvImage.java6
-rw-r--r--include/camera/Camera.h6
-rw-r--r--include/camera/CameraHardwareInterface.h54
-rw-r--r--include/camera/ICamera.h6
-rw-r--r--include/media/stagefright/CameraSource.h28
-rw-r--r--libs/camera/Camera.cpp16
-rw-r--r--libs/camera/ICamera.cpp36
-rw-r--r--location/java/android/location/LocationManager.java48
-rw-r--r--media/java/android/media/MediaFile.java1
-rw-r--r--media/java/android/media/MediaPlayer.java4
-rw-r--r--media/java/android/media/MediaScanner.java34
-rw-r--r--media/libstagefright/CameraSource.cpp22
-rw-r--r--media/libstagefright/OMXCodec.cpp5
-rw-r--r--media/libstagefright/StagefrightMediaScanner.cpp5
-rw-r--r--media/libstagefright/foundation/ALooper.cpp23
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp2
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.cpp27
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.h6
-rw-r--r--opengl/libs/GLES2_dbg/src/api.h6
-rw-r--r--opengl/libs/GLES2_dbg/src/dbgcontext.cpp33
-rw-r--r--opengl/libs/GLES2_dbg/src/header.h37
-rw-r--r--opengl/libs/GLES2_dbg/src/vertex.cpp6
-rw-r--r--opengl/tests/gl2_cameraeye/Android.mk16
-rw-r--r--opengl/tests/gl2_cameraeye/AndroidManifest.xml36
-rw-r--r--opengl/tests/gl2_cameraeye/res/values/strings.xml21
-rw-r--r--opengl/tests/gl2_cameraeye/src/com/android/gl2cameraeye/GL2CameraEye.java508
-rw-r--r--opengl/tools/glgen/specs/gles11/checks.spec34
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java17
-rw-r--r--services/camera/libcameraservice/CameraService.cpp20
-rw-r--r--services/camera/libcameraservice/CameraService.h4
-rw-r--r--services/input/InputDispatcher.cpp265
-rw-r--r--services/input/InputDispatcher.h55
-rw-r--r--services/jni/com_android_server_InputManager.cpp8
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnectionTracker.java74
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java8
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CDMAPhone.java2
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java9
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GSMPhone.java2
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java35
-rw-r--r--[-rwxr-xr-x]telephony/java/com/android/internal/telephony/sip/SipPhone.java5
-rw-r--r--voip/java/com/android/server/sip/SipHelper.java8
68 files changed, 2009 insertions, 706 deletions
diff --git a/api/current.xml b/api/current.xml
index 555f804..ded1d1b 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -9013,6 +9013,28 @@
visibility="public"
>
</field>
+<field name="state_drag_can_accept"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843621"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="state_drag_hovered"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843622"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="state_empty"
type="int"
transient="false"
@@ -267668,7 +267690,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
</parameter>
</method>
</interface>
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 9e6bcc8..533a60a 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -114,6 +114,15 @@ static void dumpstate() {
run_command("WIFI NETWORKS", 20,
"su", "root", "wpa_cli", "list_networks", NULL);
+ property_get("dhcp.wlan0.gateway", network, "");
+ if (network[0])
+ run_command("PING GATEWAY", 10, "su", "root", "ping", "-c", "3", "-i", ".5", network, NULL);
+ property_get("dhcp.wlan0.dns1", network, "");
+ if (network[0])
+ run_command("PING DNS1", 10, "su", "root", "ping", "-c", "3", "-i", ".5", network, NULL);
+ property_get("dhcp.wlan0.dns2", network, "");
+ if (network[0])
+ run_command("PING DNS2", 10, "su", "root", "ping", "-c", "3", "-i", ".5", network, NULL);
#ifdef FWDUMP_bcm4329
run_command("DUMP WIFI STATUS", 20,
"su", "root", "dhdutil", "-i", "wlan0", "dump", NULL);
diff --git a/core/java/android/text/CharSequenceIterator.java b/core/java/android/text/CharSequenceIterator.java
new file mode 100644
index 0000000..4946406
--- /dev/null
+++ b/core/java/android/text/CharSequenceIterator.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text;
+
+import android.util.MathUtils;
+
+import java.text.CharacterIterator;
+
+/** {@hide} */
+public class CharSequenceIterator implements CharacterIterator {
+ private final CharSequence mValue;
+
+ private final int mStart;
+ private final int mEnd;
+ private int mIndex;
+
+ public CharSequenceIterator(CharSequence value) {
+ mValue = value;
+ mStart = 0;
+ mEnd = value.length();
+ mIndex = 0;
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public char current() {
+ if (mIndex == mEnd) {
+ return DONE;
+ }
+ return mValue.charAt(mIndex);
+ }
+
+ /** {@inheritDoc} */
+ public int getBeginIndex() {
+ return mStart;
+ }
+
+ /** {@inheritDoc} */
+ public int getEndIndex() {
+ return mEnd;
+ }
+
+ /** {@inheritDoc} */
+ public int getIndex() {
+ return mIndex;
+ }
+
+ /** {@inheritDoc} */
+ public char first() {
+ return setIndex(mStart);
+ }
+
+ /** {@inheritDoc} */
+ public char last() {
+ return setIndex(mEnd - 1);
+ }
+
+ /** {@inheritDoc} */
+ public char next() {
+ return setIndex(mIndex + 1);
+ }
+
+ /** {@inheritDoc} */
+ public char previous() {
+ return setIndex(mIndex - 1);
+ }
+
+ /** {@inheritDoc} */
+ public char setIndex(int index) {
+ mIndex = MathUtils.constrain(index, mStart, mEnd);
+ return current();
+ }
+}
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 13cb5e6..b18570a 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -16,6 +16,11 @@
package android.text;
+import android.util.Log;
+
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+
/**
* Utility class for manipulating cursors and selections in CharSequences.
@@ -38,7 +43,7 @@ public class Selection {
else
return -1;
}
-
+
/**
* Return the offset of the selection edge or cursor, or -1 if
* there is no selection or cursor.
@@ -57,7 +62,7 @@ public class Selection {
// private static int pin(int value, int min, int max) {
// return value < min ? 0 : (value > max ? max : value);
// }
-
+
/**
* Set the selection anchor to <code>start</code> and the selection edge
* to <code>stop</code>.
@@ -69,7 +74,7 @@ public class Selection {
int ostart = getSelectionStart(text);
int oend = getSelectionEnd(text);
-
+
if (ostart != start || oend != stop) {
text.setSpan(SELECTION_START, start, start,
Spanned.SPAN_POINT_POINT|Spanned.SPAN_INTERMEDIATE);
@@ -357,6 +362,42 @@ public class Selection {
return true;
}
+ /** {@hide} */
+ public static interface PositionIterator {
+ public static final int DONE = BreakIterator.DONE;
+
+ public int preceding(int position);
+ public int following(int position);
+ }
+
+ /** {@hide} */
+ public static boolean moveToPreceding(
+ Spannable text, PositionIterator iter, boolean extendSelection) {
+ final int offset = iter.preceding(getSelectionEnd(text));
+ if (offset != PositionIterator.DONE) {
+ if (extendSelection) {
+ extendSelection(text, offset);
+ } else {
+ setSelection(text, offset);
+ }
+ }
+ return true;
+ }
+
+ /** {@hide} */
+ public static boolean moveToFollowing(
+ Spannable text, PositionIterator iter, boolean extendSelection) {
+ final int offset = iter.following(getSelectionEnd(text));
+ if (offset != PositionIterator.DONE) {
+ if (extendSelection) {
+ extendSelection(text, offset);
+ } else {
+ setSelection(text, offset);
+ }
+ }
+ return true;
+ }
+
private static int findEdge(Spannable text, Layout layout, int dir) {
int pt = getSelectionEnd(text);
int line = layout.getLineForOffset(pt);
@@ -419,7 +460,7 @@ public class Selection {
private static final class START implements NoCopySpan { }
private static final class END implements NoCopySpan { }
-
+
/*
* Public constants
*/
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index a61ff13..80c0106 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -17,14 +17,23 @@
package android.text.method;
import android.graphics.Rect;
+import android.text.CharSequenceIterator;
+import android.text.Editable;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
+import android.text.Spanned;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.util.MathUtils;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+
/**
* A movement method that provides cursor movement and selection.
* Supports displaying the context menu on DPad Center.
@@ -193,6 +202,20 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme
}
}
+ /** {@hide} */
+ @Override
+ protected boolean leftWord(TextView widget, Spannable buffer) {
+ mWordIterator.setCharSequence(buffer);
+ return Selection.moveToPreceding(buffer, mWordIterator, isSelecting(buffer));
+ }
+
+ /** {@hide} */
+ @Override
+ protected boolean rightWord(TextView widget, Spannable buffer) {
+ mWordIterator.setCharSequence(buffer);
+ return Selection.moveToFollowing(buffer, mWordIterator, isSelecting(buffer));
+ }
+
@Override
protected boolean home(TextView widget, Spannable buffer) {
return lineStart(widget, buffer);
@@ -205,7 +228,8 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
- int initialScrollX = -1, initialScrollY = -1;
+ int initialScrollX = -1;
+ int initialScrollY = -1;
final int action = event.getAction();
if (action == MotionEvent.ACTION_UP) {
@@ -220,7 +244,7 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme
boolean cap = isSelecting(buffer);
if (cap) {
int offset = widget.getOffset((int) event.getX(), (int) event.getY());
-
+
buffer.setSpan(LAST_TAP_DOWN, offset, offset, Spannable.SPAN_POINT_POINT);
// Disallow intercepting of the touch events, so that
@@ -308,6 +332,103 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme
return sInstance;
}
+ /**
+ * Walks through cursor positions at word boundaries. Internally uses
+ * {@link BreakIterator#getWordInstance()}, and caches {@link CharSequence}
+ * for performance reasons.
+ */
+ private static class WordIterator implements Selection.PositionIterator {
+ private CharSequence mCurrent;
+ private boolean mCurrentDirty = false;
+
+ private BreakIterator mIterator;
+
+ private TextWatcher mWatcher = new TextWatcher() {
+ /** {@inheritDoc} */
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // ignored
+ }
+
+ /** {@inheritDoc} */
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ mCurrentDirty = true;
+ }
+
+ /** {@inheritDoc} */
+ public void afterTextChanged(Editable s) {
+ // ignored
+ }
+ };
+
+ public void setCharSequence(CharSequence incoming) {
+ if (mIterator == null) {
+ mIterator = BreakIterator.getWordInstance();
+ }
+
+ // when incoming is different object, move listeners to new sequence
+ // and mark as dirty so we reload contents.
+ if (mCurrent != incoming) {
+ if (mCurrent instanceof Editable) {
+ ((Editable) mCurrent).removeSpan(mWatcher);
+ }
+
+ if (incoming instanceof Editable) {
+ ((Editable) incoming).setSpan(
+ mWatcher, 0, incoming.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ }
+
+ mCurrent = incoming;
+ mCurrentDirty = true;
+ }
+
+ if (mCurrentDirty) {
+ final CharacterIterator charIterator = new CharSequenceIterator(mCurrent);
+ mIterator.setText(charIterator);
+
+ mCurrentDirty = false;
+ }
+ }
+
+ private boolean isValidOffset(int offset) {
+ return offset >= 0 && offset < mCurrent.length();
+ }
+
+ private boolean isLetterOrDigit(int offset) {
+ if (isValidOffset(offset)) {
+ return Character.isLetterOrDigit(mCurrent.charAt(offset));
+ } else {
+ return false;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public int preceding(int offset) {
+ // always round cursor index into valid string index
+ offset = MathUtils.constrain(offset, 0, mCurrent.length() - 1);
+
+ do {
+ offset = mIterator.preceding(offset);
+ if (isLetterOrDigit(offset)) break;
+ } while (isValidOffset(offset));
+
+ return offset;
+ }
+
+ /** {@inheritDoc} */
+ public int following(int offset) {
+ // always round cursor index into valid string index
+ offset = MathUtils.constrain(offset, 0, mCurrent.length() - 1);
+
+ do {
+ offset = mIterator.following(offset);
+ if (isLetterOrDigit(offset - 1)) break;
+ } while (isValidOffset(offset));
+
+ return offset;
+ }
+ }
+
+ private WordIterator mWordIterator = new WordIterator();
private static final Object LAST_TAP_DOWN = new Object();
private static ArrowKeyMovementMethod sInstance;
diff --git a/core/java/android/text/method/BaseMovementMethod.java b/core/java/android/text/method/BaseMovementMethod.java
index 94c6ed0..f554b90 100644
--- a/core/java/android/text/method/BaseMovementMethod.java
+++ b/core/java/android/text/method/BaseMovementMethod.java
@@ -164,6 +164,9 @@ public class BaseMovementMethod implements MovementMethod {
if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
return left(widget, buffer);
} else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+ KeyEvent.META_CTRL_ON)) {
+ return leftWord(widget, buffer);
+ } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
KeyEvent.META_ALT_ON)) {
return lineStart(widget, buffer);
}
@@ -173,6 +176,9 @@ public class BaseMovementMethod implements MovementMethod {
if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
return right(widget, buffer);
} else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+ KeyEvent.META_CTRL_ON)) {
+ return rightWord(widget, buffer);
+ } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
KeyEvent.META_ALT_ON)) {
return lineEnd(widget, buffer);
}
@@ -217,12 +223,18 @@ public class BaseMovementMethod implements MovementMethod {
case KeyEvent.KEYCODE_MOVE_HOME:
if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
return home(widget, buffer);
+ } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+ KeyEvent.META_CTRL_ON)) {
+ return top(widget, buffer);
}
break;
case KeyEvent.KEYCODE_MOVE_END:
if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
return end(widget, buffer);
+ } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+ KeyEvent.META_CTRL_ON)) {
+ return bottom(widget, buffer);
}
break;
}
@@ -349,6 +361,16 @@ public class BaseMovementMethod implements MovementMethod {
return false;
}
+ /** {@hide} */
+ protected boolean leftWord(TextView widget, Spannable buffer) {
+ return false;
+ }
+
+ /** {@hide} */
+ protected boolean rightWord(TextView widget, Spannable buffer) {
+ return false;
+ }
+
/**
* Performs a home movement action.
* Moves the cursor or scrolls to the start of the line or to the top of the
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 96cddfa..0ef56cc 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1305,6 +1305,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
static final int VIEW_STATE_ACTIVATED = 1 << 5;
static final int VIEW_STATE_ACCELERATED = 1 << 6;
static final int VIEW_STATE_HOVERED = 1 << 7;
+ static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
+ static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
static final int[] VIEW_STATE_IDS = new int[] {
R.attr.state_window_focused, VIEW_STATE_WINDOW_FOCUSED,
@@ -1315,6 +1317,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
R.attr.state_activated, VIEW_STATE_ACTIVATED,
R.attr.state_accelerated, VIEW_STATE_ACCELERATED,
R.attr.state_hovered, VIEW_STATE_HOVERED,
+ R.attr.state_drag_can_accept, VIEW_STATE_DRAG_CAN_ACCEPT,
+ R.attr.state_drag_hovered, VIEW_STATE_DRAG_HOVERED,
};
static {
@@ -1651,6 +1655,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/
static final int INVALIDATED = 0x80000000;
+ /* Masks for mPrivateFlags2 */
+
+ /**
+ * Indicates that this view has reported that it can accept the current drag's content.
+ * Cleared when the drag operation concludes.
+ * @hide
+ */
+ static final int DRAG_CAN_ACCEPT = 0x00000001;
+
+ /**
+ * Indicates that this view is currently directly under the drag location in a
+ * drag-and-drop operation involving content that it can accept. Cleared when
+ * the drag exits the view, or when the drag operation concludes.
+ * @hide
+ */
+ static final int DRAG_HOVERED = 0x00000002;
+
+ /* End of masks for mPrivateFlags2 */
+
+ static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
+
/**
* Always allow a user to over-scroll this view, provided it is a
* view that can scroll.
@@ -1822,6 +1847,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
@ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
})
int mPrivateFlags;
+ int mPrivateFlags2;
/**
* This view's request for the visibility of the status bar.
@@ -2251,12 +2277,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
private ViewPropertyAnimator mAnimator = null;
/**
- * Cache drag/drop state
- *
- */
- boolean mCanAcceptDrop;
-
- /**
* Flag indicating that a drag can cross window boundaries. When
* {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
* with this flag set, all visible applications will be able to participate
@@ -10035,6 +10055,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
+ final int privateFlags2 = mPrivateFlags2;
+ if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
+ if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
+
drawableState = VIEW_STATE_SETS[viewStateIndex];
//noinspection ConstantIfStatement
@@ -11701,6 +11725,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
return onDragEvent(event);
}
+ boolean canAcceptDrag() {
+ return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
+ }
+
/**
* This needs to be a better API (NOT ON VIEW) before it is exposed. If
* it is ever exposed at all.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 058b826..f7f2685 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -929,6 +929,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
final View child = children[i];
+ child.mPrivateFlags2 &= ~View.DRAG_MASK;
if (child.getVisibility() == VISIBLE) {
final boolean handled = notifyChildOfDrag(children[i]);
if (handled) {
@@ -949,6 +950,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
for (View child : mDragNotifiedChildren) {
// If a child was notified about an ongoing drag, it's told that it's over
child.dispatchDragEvent(event);
+ child.mPrivateFlags2 &= ~View.DRAG_MASK;
+ child.refreshDrawableState();
}
mDragNotifiedChildren.clear();
@@ -979,8 +982,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final int action = event.mAction;
// If we've dragged off of a child view, send it the EXITED message
if (mCurrentDragView != null) {
+ final View view = mCurrentDragView;
event.mAction = DragEvent.ACTION_DRAG_EXITED;
- mCurrentDragView.dispatchDragEvent(event);
+ view.dispatchDragEvent(event);
+ view.mPrivateFlags2 &= ~View.DRAG_HOVERED;
+ view.refreshDrawableState();
}
mCurrentDragView = target;
@@ -988,6 +994,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (target != null) {
event.mAction = DragEvent.ACTION_DRAG_ENTERED;
target.dispatchDragEvent(event);
+ target.mPrivateFlags2 |= View.DRAG_HOVERED;
+ target.refreshDrawableState();
}
event.mAction = action; // restore the event's original state
}
@@ -1018,7 +1026,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
case DragEvent.ACTION_DRAG_EXITED: {
if (mCurrentDragView != null) {
- mCurrentDragView.dispatchDragEvent(event);
+ final View view = mCurrentDragView;
+ view.dispatchDragEvent(event);
+ view.mPrivateFlags2 &= ~View.DRAG_HOVERED;
+ view.refreshDrawableState();
+
mCurrentDragView = null;
}
} break;
@@ -1056,7 +1068,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final View[] children = mChildren;
for (int i = count - 1; i >= 0; i--) {
final View child = children[i];
- if (!child.mCanAcceptDrop) {
+ if (!child.canAcceptDrag()) {
continue;
}
@@ -1072,11 +1084,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
Log.d(View.VIEW_LOG_TAG, "Sending drag-started to view: " + child);
}
+ boolean canAccept = false;
if (! mDragNotifiedChildren.contains(child)) {
mDragNotifiedChildren.add(child);
- child.mCanAcceptDrop = child.dispatchDragEvent(mCurrentDrag);
+ canAccept = child.dispatchDragEvent(mCurrentDrag);
+ if (canAccept && !child.canAcceptDrag()) {
+ child.mPrivateFlags2 |= View.DRAG_CAN_ACCEPT;
+ child.refreshDrawableState();
+ }
}
- return child.mCanAcceptDrop;
+ return canAccept;
}
@Override
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java
index 8ea73b5..ad6e5d3 100644
--- a/core/java/android/webkit/HTML5VideoView.java
+++ b/core/java/android/webkit/HTML5VideoView.java
@@ -15,7 +15,7 @@ import java.util.TimerTask;
/**
* @hide This is only used by the browser
*/
-public class HTML5VideoView implements MediaPlayer.OnPreparedListener{
+public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
protected static final String LOGTAG = "HTML5VideoView";
@@ -189,6 +189,10 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{
mPlayer.setOnPreparedListener(this);
}
+ public void setOnInfoListener(HTML5VideoViewProxy proxy) {
+ mPlayer.setOnInfoListener(proxy);
+ }
+
// Normally called immediately after setVideoURI. But for full screen,
// this should be after surface holder created
public void prepareDataAndDisplayMode(HTML5VideoViewProxy proxy) {
@@ -198,7 +202,7 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{
setOnCompletionListener(proxy);
setOnPreparedListener(proxy);
setOnErrorListener(proxy);
-
+ setOnInfoListener(proxy);
// When there is exception, we could just bail out silently.
// No Video will be played though. Write the stack for debug
try {
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index acd7eab..0ee1566 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -46,6 +46,7 @@ class HTML5VideoViewProxy extends Handler
implements MediaPlayer.OnPreparedListener,
MediaPlayer.OnCompletionListener,
MediaPlayer.OnErrorListener,
+ MediaPlayer.OnInfoListener,
SurfaceTexture.OnFrameAvailableListener {
// Logging tag.
private static final String LOGTAG = "HTML5VideoViewProxy";
@@ -56,6 +57,8 @@ class HTML5VideoViewProxy extends Handler
private static final int PAUSE = 102;
private static final int ERROR = 103;
private static final int LOAD_DEFAULT_POSTER = 104;
+ private static final int BUFFERING_START = 105;
+ private static final int BUFFERING_END = 106;
// Message Ids to be handled on the WebCore thread
private static final int PREPARED = 200;
@@ -92,6 +95,8 @@ class HTML5VideoViewProxy extends Handler
// identify the exact layer on the UI thread to use the SurfaceTexture.
private static int mBaseLayer = 0;
+ // This is true only when the player is buffering and paused
+ private static boolean mPlayerBuffering = false;
// Every time webView setBaseLayer, this will be called.
// When we found the Video layer, then we set the Surface Texture to it.
// Otherwise, we may want to delete the Surface Texture to save memory.
@@ -106,6 +111,8 @@ class HTML5VideoViewProxy extends Handler
int currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) {
int playerState = mHTML5VideoView.getCurrentState();
+ if (mPlayerBuffering)
+ playerState = HTML5VideoView.STATE_NOTPREPARED;
boolean foundInTree = nativeSendSurfaceTexture(surfTexture,
layer, currentVideoLayerId, textureName,
playerState);
@@ -159,7 +166,7 @@ class HTML5VideoViewProxy extends Handler
WebChromeClient client, int videoLayerId) {
int currentVideoLayerId = -1;
boolean backFromFullScreenMode = false;
-
+ mPlayerBuffering = false;
if (mHTML5VideoView != null) {
currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
if (mHTML5VideoView instanceof HTML5VideoFullScreen) {
@@ -224,6 +231,7 @@ class HTML5VideoViewProxy extends Handler
}
public static void onPrepared() {
+ mPlayerBuffering = false;
// The VideoView will decide whether to really kick off to play.
mHTML5VideoView.start();
if (mBaseLayer != 0) {
@@ -341,6 +349,14 @@ class HTML5VideoViewProxy extends Handler
}
break;
}
+ case BUFFERING_START: {
+ VideoPlayer.mPlayerBuffering = true;
+ break;
+ }
+ case BUFFERING_END: {
+ VideoPlayer.mPlayerBuffering = false;
+ break;
+ }
}
}
@@ -670,4 +686,14 @@ class HTML5VideoViewProxy extends Handler
private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture,
int baseLayer, int videoLayerId, int textureName,
int playerState);
+
+ @Override
+ public boolean onInfo(MediaPlayer mp, int what, int extra) {
+ if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
+ sendMessage(obtainMessage(BUFFERING_START, what, extra));
+ } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
+ sendMessage(obtainMessage(BUFFERING_END, what, extra));
+ }
+ return false;
+ }
}
diff --git a/core/jni/android_bluetooth_HeadsetBase.cpp b/core/jni/android_bluetooth_HeadsetBase.cpp
index bbf1ae5..5b21c56 100644
--- a/core/jni/android_bluetooth_HeadsetBase.cpp
+++ b/core/jni/android_bluetooth_HeadsetBase.cpp
@@ -96,11 +96,12 @@ static int send_line(int fd, const char* line) {
return 0;
}
-static int is_ascii(char *line) {
- for (;;line++) {
- if (*line == 0) return 1;
- if (*line >> 7) return 0;
- }
+static void mask_eighth_bit(char *line)
+{
+ for (;;line++) {
+ if (0 == *line) return;
+ *line &= 0x7F;
+ }
}
static const char* get_line(int fd, char *buf, int len, int timeout_ms,
@@ -164,16 +165,15 @@ again:
*bufit = NULL;
- // Simple validation. Must be all ASCII.
- // (we sometimes send non-ASCII UTF-8 in address book, but should
- // never receive non-ASCII UTF-8).
- // This was added because of the BMW 2005 E46 which sends binary junk.
- if (is_ascii(buf)) {
- IF_LOGV() LOG(LOG_VERBOSE, "Bluetooth AT recv", "%s", buf);
- } else {
- LOGW("Ignoring invalid AT command: %s", buf);
- buf[0] = NULL;
- }
+ // According to ITU V.250 section 5.1, IA5 7 bit chars are used,
+ // the eighth bit or higher bits are ignored if they exists
+ // We mask out only eighth bit, no higher bit, since we do char
+ // string here, not wide char.
+ // We added this processing due to 2 real world problems.
+ // 1 BMW 2005 E46 which sends binary junk
+ // 2 Audi 2010 A3, dial command use 0xAD (soft-hyphen) as number
+ // formater, which was rejected by the AT handler
+ mask_eighth_bit(buf);
return buf;
}
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 0f71b9f..1c326ba 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -533,16 +533,69 @@ android_glGetBooleanv__ILjava_nio_IntBuffer_2
static void
android_glGetBufferParameteriv__II_3II
(JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetBufferParameteriv");
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ if (_remaining < 1) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < 1");
+ goto exit;
+ }
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetBufferParameteriv(
+ (GLenum)target,
+ (GLenum)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
static void
android_glGetBufferParameteriv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetBufferParameteriv");
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ if (_remaining < 1) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < 1");
+ goto exit;
+ }
+ glGetBufferParameteriv(
+ (GLenum)target,
+ (GLenum)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) */
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 942a0d9..1390506 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -1621,171 +1621,495 @@ android_glTranslatexOES__III
static jboolean
android_glIsRenderbufferOES__I
(JNIEnv *_env, jobject _this, jint renderbuffer) {
- _env->ThrowNew(UOEClass,
- "glIsRenderbufferOES");
- return JNI_FALSE;
+ GLboolean _returnValue;
+ _returnValue = glIsRenderbufferOES(
+ (GLuint)renderbuffer
+ );
+ return _returnValue;
}
/* void glBindRenderbufferOES ( GLenum target, GLuint renderbuffer ) */
static void
android_glBindRenderbufferOES__II
(JNIEnv *_env, jobject _this, jint target, jint renderbuffer) {
- _env->ThrowNew(UOEClass,
- "glBindRenderbufferOES");
+ glBindRenderbufferOES(
+ (GLenum)target,
+ (GLuint)renderbuffer
+ );
}
/* void glDeleteRenderbuffersOES ( GLsizei n, const GLuint *renderbuffers ) */
static void
android_glDeleteRenderbuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glDeleteRenderbuffersOES");
+ GLuint *renderbuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ if (!renderbuffers_ref) {
+ _env->ThrowNew(IAEClass, "renderbuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
+ if (_remaining < n) {
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ renderbuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(renderbuffers_ref, (jboolean *)0);
+ renderbuffers = renderbuffers_base + offset;
+
+ glDeleteRenderbuffersOES(
+ (GLsizei)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (renderbuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
+ JNI_ABORT);
+ }
}
/* void glDeleteRenderbuffersOES ( GLsizei n, const GLuint *renderbuffers ) */
static void
android_glDeleteRenderbuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glDeleteRenderbuffersOES");
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glDeleteRenderbuffersOES(
+ (GLsizei)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, renderbuffers, JNI_FALSE);
+ }
}
/* void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers ) */
static void
android_glGenRenderbuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGenRenderbuffersOES");
+ jint _exception = 0;
+ GLuint *renderbuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ if (!renderbuffers_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "renderbuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ renderbuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(renderbuffers_ref, (jboolean *)0);
+ renderbuffers = renderbuffers_base + offset;
+
+ glGenRenderbuffersOES(
+ (GLsizei)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (renderbuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers ) */
static void
android_glGenRenderbuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glGenRenderbuffersOES");
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glGenRenderbuffersOES(
+ (GLsizei)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glRenderbufferStorageOES ( GLenum target, GLenum internalformat, GLsizei width, GLsizei height ) */
static void
android_glRenderbufferStorageOES__IIII
(JNIEnv *_env, jobject _this, jint target, jint internalformat, jint width, jint height) {
- _env->ThrowNew(UOEClass,
- "glRenderbufferStorageOES");
+ glRenderbufferStorageOES(
+ (GLenum)target,
+ (GLenum)internalformat,
+ (GLsizei)width,
+ (GLsizei)height
+ );
}
/* void glGetRenderbufferParameterivOES ( GLenum target, GLenum pname, GLint *params ) */
static void
android_glGetRenderbufferParameterivOES__II_3II
(JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetRenderbufferParameterivOES");
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ if (_remaining < 1) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < 1");
+ goto exit;
+ }
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetRenderbufferParameterivOES(
+ (GLenum)target,
+ (GLenum)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetRenderbufferParameterivOES ( GLenum target, GLenum pname, GLint *params ) */
static void
android_glGetRenderbufferParameterivOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetRenderbufferParameterivOES");
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ if (_remaining < 1) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < 1");
+ goto exit;
+ }
+ glGetRenderbufferParameterivOES(
+ (GLenum)target,
+ (GLenum)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* GLboolean glIsFramebufferOES ( GLuint framebuffer ) */
static jboolean
android_glIsFramebufferOES__I
(JNIEnv *_env, jobject _this, jint framebuffer) {
- _env->ThrowNew(UOEClass,
- "glIsFramebufferOES");
- return JNI_FALSE;
+ GLboolean _returnValue;
+ _returnValue = glIsFramebufferOES(
+ (GLuint)framebuffer
+ );
+ return _returnValue;
}
/* void glBindFramebufferOES ( GLenum target, GLuint framebuffer ) */
static void
android_glBindFramebufferOES__II
(JNIEnv *_env, jobject _this, jint target, jint framebuffer) {
- _env->ThrowNew(UOEClass,
- "glBindFramebufferOES");
+ glBindFramebufferOES(
+ (GLenum)target,
+ (GLuint)framebuffer
+ );
}
/* void glDeleteFramebuffersOES ( GLsizei n, const GLuint *framebuffers ) */
static void
android_glDeleteFramebuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glDeleteFramebuffersOES");
+ GLuint *framebuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ if (!framebuffers_ref) {
+ _env->ThrowNew(IAEClass, "framebuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
+ if (_remaining < n) {
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ framebuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(framebuffers_ref, (jboolean *)0);
+ framebuffers = framebuffers_base + offset;
+
+ glDeleteFramebuffersOES(
+ (GLsizei)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (framebuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
+ JNI_ABORT);
+ }
}
/* void glDeleteFramebuffersOES ( GLsizei n, const GLuint *framebuffers ) */
static void
android_glDeleteFramebuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glDeleteFramebuffersOES");
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glDeleteFramebuffersOES(
+ (GLsizei)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, framebuffers, JNI_FALSE);
+ }
}
/* void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers ) */
static void
android_glGenFramebuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGenFramebuffersOES");
+ jint _exception = 0;
+ GLuint *framebuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ if (!framebuffers_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "framebuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ framebuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(framebuffers_ref, (jboolean *)0);
+ framebuffers = framebuffers_base + offset;
+
+ glGenFramebuffersOES(
+ (GLsizei)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (framebuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers ) */
static void
android_glGenFramebuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glGenFramebuffersOES");
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glGenFramebuffersOES(
+ (GLsizei)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* GLenum glCheckFramebufferStatusOES ( GLenum target ) */
static jint
android_glCheckFramebufferStatusOES__I
(JNIEnv *_env, jobject _this, jint target) {
- _env->ThrowNew(UOEClass,
- "glCheckFramebufferStatusOES");
- return 0;
+ GLenum _returnValue;
+ _returnValue = glCheckFramebufferStatusOES(
+ (GLenum)target
+ );
+ return _returnValue;
}
/* void glFramebufferRenderbufferOES ( GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer ) */
static void
android_glFramebufferRenderbufferOES__IIII
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint renderbuffertarget, jint renderbuffer) {
- _env->ThrowNew(UOEClass,
- "glFramebufferRenderbufferOES");
+ glFramebufferRenderbufferOES(
+ (GLenum)target,
+ (GLenum)attachment,
+ (GLenum)renderbuffertarget,
+ (GLuint)renderbuffer
+ );
}
/* void glFramebufferTexture2DOES ( GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level ) */
static void
android_glFramebufferTexture2DOES__IIIII
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint textarget, jint texture, jint level) {
- _env->ThrowNew(UOEClass,
- "glFramebufferTexture2DOES");
+ glFramebufferTexture2DOES(
+ (GLenum)target,
+ (GLenum)attachment,
+ (GLenum)textarget,
+ (GLuint)texture,
+ (GLint)level
+ );
}
/* void glGetFramebufferAttachmentParameterivOES ( GLenum target, GLenum attachment, GLenum pname, GLint *params ) */
static void
android_glGetFramebufferAttachmentParameterivOES__III_3II
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetFramebufferAttachmentParameterivOES");
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ if (_remaining < 1) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < 1");
+ goto exit;
+ }
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetFramebufferAttachmentParameterivOES(
+ (GLenum)target,
+ (GLenum)attachment,
+ (GLenum)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetFramebufferAttachmentParameterivOES ( GLenum target, GLenum attachment, GLenum pname, GLint *params ) */
static void
android_glGetFramebufferAttachmentParameterivOES__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetFramebufferAttachmentParameterivOES");
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ if (_remaining < 1) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < 1");
+ goto exit;
+ }
+ glGetFramebufferAttachmentParameterivOES(
+ (GLenum)target,
+ (GLenum)attachment,
+ (GLenum)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGenerateMipmapOES ( GLenum target ) */
static void
android_glGenerateMipmapOES__I
(JNIEnv *_env, jobject _this, jint target) {
- _env->ThrowNew(UOEClass,
- "glGenerateMipmapOES");
+ glGenerateMipmapOES(
+ (GLenum)target
+ );
}
/* void glCurrentPaletteMatrixOES ( GLuint matrixpaletteindex ) */
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index ef25319..7ac0f6e 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -249,16 +249,19 @@ android_glBlendColor__FFFF
static void
android_glBlendEquation__I
(JNIEnv *_env, jobject _this, jint mode) {
- _env->ThrowNew(UOEClass,
- "glBlendEquation");
+ glBlendEquation(
+ (GLenum)mode
+ );
}
/* void glBlendEquationSeparate ( GLenum modeRGB, GLenum modeAlpha ) */
static void
android_glBlendEquationSeparate__II
(JNIEnv *_env, jobject _this, jint modeRGB, jint modeAlpha) {
- _env->ThrowNew(UOEClass,
- "glBlendEquationSeparate");
+ glBlendEquationSeparate(
+ (GLenum)modeRGB,
+ (GLenum)modeAlpha
+ );
}
/* void glBlendFunc ( GLenum sfactor, GLenum dfactor ) */
@@ -275,8 +278,12 @@ android_glBlendFunc__II
static void
android_glBlendFuncSeparate__IIII
(JNIEnv *_env, jobject _this, jint srcRGB, jint dstRGB, jint srcAlpha, jint dstAlpha) {
- _env->ThrowNew(UOEClass,
- "glBlendFuncSeparate");
+ glBlendFuncSeparate(
+ (GLenum)srcRGB,
+ (GLenum)dstRGB,
+ (GLenum)srcAlpha,
+ (GLenum)dstAlpha
+ );
}
/* void glBufferData ( GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage ) */
@@ -1643,16 +1650,69 @@ android_glGetBooleanv__ILjava_nio_IntBuffer_2
static void
android_glGetBufferParameteriv__II_3II
(JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetBufferParameteriv");
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ if (_remaining < 1) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < 1");
+ goto exit;
+ }
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetBufferParameteriv(
+ (GLenum)target,
+ (GLenum)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
static void
android_glGetBufferParameteriv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetBufferParameteriv");
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ if (_remaining < 1) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < 1");
+ goto exit;
+ }
+ glGetBufferParameteriv(
+ (GLenum)target,
+ (GLenum)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* GLenum glGetError ( void ) */
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e2c440a..77f4e01 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3818,6 +3818,8 @@
<li>"state_grow"
<li>"state_move"
<li>"state_hovered"
+ <li>"state_drag_can_accept"
+ <li>"state_drag_hovered"
</ul> -->
<declare-styleable name="DrawableStates">
<!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
@@ -3870,6 +3872,14 @@
<!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
set when a pointer is hovering over the view. -->
<attr name="state_hovered" format="boolean" />
+ <!-- State for {@link android.graphics.drawable.StateListDrawable StateListDrawable}
+ indicating that the Drawable is in a view that is capable of accepting a drop of
+ the content currently being manipulated in a drag-and-drop operation. -->
+ <attr name="state_drag_can_accept" format="boolean" />
+ <!-- State for {@link android.graphics.drawable.StateListDrawable StateListDrawable}
+ indicating that a drag operation (for which the Drawable's view is a valid recipient)
+ is currently positioned over the Drawable. -->
+ <attr name="state_drag_hovered" format="boolean" />
</declare-styleable>
<declare-styleable name="ViewDrawableStates">
<attr name="state_pressed" />
@@ -3880,6 +3890,8 @@
<attr name="state_activated" />
<attr name="state_accelerated" />
<attr name="state_hovered" />
+ <attr name="state_drag_can_accept" />
+ <attr name="state_drag_hovered" />
</declare-styleable>
<!-- State array representing a menu item that is currently checked. -->
<declare-styleable name="MenuItemCheckedState">
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5432212..0fefbf2 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1654,5 +1654,7 @@
=============================================================== -->
<eat-comment />
<public type="attr" name="state_hovered" />
+ <public type="attr" name="state_drag_can_accept" />
+ <public type="attr" name="state_drag_hovered" />
</resources>
diff --git a/docs/html/guide/market/billing/billing_about.jd b/docs/html/guide/market/billing/billing_about.jd
index ed45c19..5924170 100755
--- a/docs/html/guide/market/billing/billing_about.jd
+++ b/docs/html/guide/market/billing/billing_about.jd
@@ -25,66 +25,6 @@ parent.link=index.html
</div>
</div>
-<p>The in-app billing release has now entered the testing phase. During this phase we are providing <a href="{@docRoot}guide/market/billing/index.html">documentation</a> and a <a href="{@docRoot}guide/market/billing/billing_integrate.html#billing-download">sample application</a> that shows you how to implement in-app billing. You can use these resources to start designing and testing your in-app billing implementations.</p>
+<p>Android Market In-app Billing has reached the final launch milestone and is now available to developers and users. You can now publish applications that use Android Market's in-app billing service, and users can make in-app purchases. To find out how to implement in-app billing in your applications, see the <a href="{@docRoot}guide/market/billing/index.html">documentation</a> and the <a href="{@docRoot}guide/market/billing/billing_integrate.html#billing-download">sample application</a>.</p>
-<p>Following the testing phase we will launch in-app billing to the general public (see table 1 for a summary launch milestones).
-<p class="table-caption"><strong>Table 1.</strong> Summary of launch milestones for in-app billing.</p>
-
-<table>
-
-<tr>
-<th>Release Phase</th>
-<th>Status</th>
-<th>Description</th>
-</tr>
-<tr>
- <td>Early Development</td>
- <td>Completed</td>
- <td>Provided an early look at the documentation and the sample application.</td>
-</tr>
-<tr>
- <td>Test Development</td>
- <td>In process</td>
- <td>You can perform static testing with reserved product IDs and end-to-end testing with real product IDs. You cannot publish applications that use in-app billing.</td>
-</tr>
-<tr>
- <td>Final Release</td>
- <td>Coming soon</td>
- <td>You can perform static testing with reserved product IDs and end-to-end testing with real product IDs. You can publish applications that use in-app billing.</td>
-</tr>
-
-</table>
-
-<p>During the testing phase we are releasing version 2.3.4 of the Android Market application and version 5.0.12 of the MyApps application. To support in-app billing, devices running Android 3.0 must have version 5.0.12 (or higher) of the MyApps application. Devices running all other versions of Android must have version 2.3.4 (or higher) of the Android Market application. Table 2 summarizes these requirements.</p>
-
-<p class="table-caption"><strong>Table 2.</strong> Summary of in-app billing requirements.</p>
-
-<table>
-
-<tr>
-<th>If your device is running this...</th>
-<th>In-app billing requires this</th>
-</tr>
-<tr>
- <td>Android 1.6</td>
- <td>Android Market 2.3.4 (or higher)</td>
-</tr>
-<tr>
- <td>Android 2.x</td>
- <td>Android Market 2.3.4 (or higher)</td>
-</tr>
-<tr>
- <td>Android 3.0</td>
- <td>MyApps 5.0.12 (or higher)</td>
-</tr>
-
-</table>
-
-<p class="note"><strong>Note:</strong> To learn how to check the version of the Android Market application, see <a href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Android Market</a>. To learn about other requirements for in-app billing, see <a href="{@docRoot}guide/market/billing/billing_overview.html#billing-limitations">Requirements and Limitations.</a></p>
-
-<p>You can test your in-app billing implementation two ways during the testing phase: you can use the <a href="{@docRoot}guide/market/billing/billing_testing.html#billing-testing-static">reserved product IDs</a> to test static responses or you can use <a href="{@docRoot}guide/market/billing/billing_testing.html#billing-testing-real">your own product IDs</a> to test end-to-end in-app purchases. To perform end-to-end testing you need to upload your application as a draft application and add products to the application's product list.</p>
-
-<p>During the testing phase, you cannot publish applications that use in-app billing; you can only upload the applications as draft applications. After the testing phase is complete, we will launch in-app billing to the general public and you will be able to publish applications that use in-app billing.</p>
-
-<p>This documentation may change as we move from the testing phase to the final release. Be sure to check this documentation frequently for updates.</p>
diff --git a/docs/html/guide/market/billing/billing_admin.jd b/docs/html/guide/market/billing/billing_admin.jd
index 16a2a36..38099ee 100755
--- a/docs/html/guide/market/billing/billing_admin.jd
+++ b/docs/html/guide/market/billing/billing_admin.jd
@@ -28,28 +28,24 @@ parent.link=index.html
</div>
</div>
-<div class="special" style="margin-right:345px">
- <p>During the testing phase of the in-app billing release you cannot publish applications that implement in-app billing. You can only upload in-app billing applications as draft applications. For more information, see <a href="{@docRoot}guide/market/billing/billing_about.html">About this Release</a></p>
-</div>
-
<p>In-app billing frees you from processing financial transactions, but you still need to perform a few administrative tasks, including setting up and maintaining your product list on the publisher site, registering test accounts, and handling refunds when necessary.</p>
<p>You must have an Android Market publisher account to register test accounts. And you must have a Google Checkout Merchant account to create a product list and issue refunds to your users. If you already have a publisher account on Android Market, you can use your existing account. You do not need to register for a new account to support in-app billing. If you do not have a publisher account, you can register as an Android Market developer and set up a publisher account at the Android Market <a href="http://market.android.com/publish">publisher site</a>. If you do not have a Google Checkout Merchant account, you can register for one at the <a href="http://checkout.google.com">Google Checkout site</a>.</p>
<h2 id="billing-list-setup">Creating a Product List</h2>
-<p>The Android Market publisher site provides a product list for each of your published applications. You can sell an item using the in-app billing feature only if the item is listed on an application's product list. Each application has its own product list; you cannot sell items that are listed in another application's product list.</p>
+<p>The Android Market publisher site provides a product list for each of your published applications. You can sell an item using Android Market's in-app billing feature only if the item is listed on an application's product list. Each application has its own product list; you cannot sell items that are listed in another application's product list.</p>
<p>You can access an application's product list by clicking the <strong>In-App Products</strong> link that appears under each of the applications that are listed for your publisher account (see figure 1). The <strong>In-App Products</strong> link appears only if you have a Google Checkout Merchant account and an application's manifest includes the <code>com.android.vending.BILLING</code> permission.</p>
-<img src="{@docRoot}images/billing_product_list_entry.png" height="540" id="figure1" />
+<img src="{@docRoot}images/billing_product_list_entry.png" height="548" id="figure1" />
<p class="img-caption">
<strong>Figure 1.</strong> You can access an application's product list by clicking the <strong>In-App Products</strong> link.
</p>
<p>A product list contains information about the items you are selling, such as a product id, product description, and price (see figure 2). The product list stores only metadata about the items you are selling in your application. It does not store any digital content. You are responsible for storing and delivering the digital content that you sell in your applications.</p>
-<img src="{@docRoot}images/billing_product_list.png" height="742" id="figure2" />
+<img src="{@docRoot}images/billing_product_list.png" height="560" id="figure2" />
<p class="img-caption">
<strong>Figure 2.</strong> An application's product list.
</p>
@@ -65,7 +61,7 @@ parent.link=index.html
<li>On the Create New In-app Product page (see figure 3), provide details about the item you are selling and then click <strong>Save</strong>.</li>
</ol>
-<img src="{@docRoot}images/billing_list_form.png" height="854" id="figure3" />
+<img src="{@docRoot}images/billing_list_form.png" height="840" id="figure3" />
<p class="img-caption">
f<strong>Figure 3.</strong> The Create New In-app Product page lets you add items to an application's product list.
</p>
@@ -117,7 +113,7 @@ parent.link=index.html
<h2 id="billing-refunds">Handling Refunds</h2>
-<p>The in-app billing feature does not allow users to send a refund request to Android Market. Refunds for purchases that were made with the in-app billing feature must be directed to you (the application developer). You can then process the refund through your Google Checkout Merchant account. When you do this, Android Market receives a refund notification from Google Checkout, and Android Market sends a refund message to your application. For more information, see <a href="{@docRoot}guide/market/billing/billing_overview.html#billing-action-notify">Handling IN_APP_NOTIFY messages</a> and <a href="http://www.google.com/support/androidmarket/bin/answer.py?answer=1153485">In-app Billing Pricing</a>.</p>
+<p>In-app billing does not allow users to send a refund request to Android Market. Refunds for in-app purchases must be directed to you (the application developer). You can then process the refund through your Google Checkout Merchant account. When you do this, Android Market receives a refund notification from Google Checkout, and Android Market sends a refund message to your application. For more information, see <a href="{@docRoot}guide/market/billing/billing_overview.html#billing-action-notify">Handling IN_APP_NOTIFY messages</a> and <a href="http://www.google.com/support/androidmarket/bin/answer.py?answer=1153485">In-app Billing Pricing</a>.</p>
<h2 id="billing-testing-setup">Setting Up Test Accounts</h2>
@@ -171,12 +167,6 @@ parent.link=index.html
href="http://stackoverflow.com/questions/tagged/android">http://stackoverflow.com/questions/tagged/android</a></td>
</tr>
<tr>
-<td>Accounts, publishing, and deployment issues</td>
-<td><a href="http://www.google.com/support/forum/p/Android+Market">Android
-Market Help Forum</a></td>
-<td>Publisher accounts, Android Market key pair, test accounts, server responses, test responses, application deployment and results.</td>
-</tr>
-<tr>
<td>Market billing issue tracker</td>
<td><a href="http://code.google.com/p/marketbilling/issues/">Market billing
project issue tracker</a></td>
diff --git a/docs/html/guide/market/billing/billing_best_practices.jd b/docs/html/guide/market/billing/billing_best_practices.jd
index a505de4..6f9f64c 100755
--- a/docs/html/guide/market/billing/billing_best_practices.jd
+++ b/docs/html/guide/market/billing/billing_best_practices.jd
@@ -24,11 +24,7 @@ parent.link=index.html
</div>
</div>
-<div class="special" style="margin-right:345px">
- <p>During the testing phase of the in-app billing release you cannot publish applications that implement in-app billing. You can only upload in-app billing applications as draft applications. For more information, see <a href="{@docRoot}guide/market/billing/billing_about.html">About this Release</a></p>
-</div>
-
-<p>As you design your in-app billing implementation, be sure to follow the security and design guidelines that are discussed in this document. These guidelines are recommended best practices for anyone who is using the Android Market in-app billing service and can be incorporated into any in-app billing implementation.</p>
+<p>As you design your in-app billing implementation, be sure to follow the security and design guidelines that are discussed in this document. These guidelines are recommended best practices for anyone who is using Android Market's in-app billing service.</p>
<h2>Security Best Practices</h2>
diff --git a/docs/html/guide/market/billing/billing_integrate.jd b/docs/html/guide/market/billing/billing_integrate.jd
index d027686..26bda66 100755
--- a/docs/html/guide/market/billing/billing_integrate.jd
+++ b/docs/html/guide/market/billing/billing_integrate.jd
@@ -30,11 +30,7 @@ parent.link=index.html
</div>
</div>
-<div class="special" style="margin-right:345px">
- <p>During the testing phase of the in-app billing release you cannot publish applications that implement in-app billing. You can only upload in-app billing applications as draft applications. For more information, see <a href="{@docRoot}guide/market/billing/billing_about.html">About this Release</a></p>
-</div>
-
-<p>The Android Market in-app billing service provides a straightforward, simple interface for sending in-app billing requests and managing in-app billing transactions using Android Market. This document helps you implement in-app billing by stepping through the primary implementation tasks, using the in-app billing sample application as an example.</p>
+<p>Android Market In-app Billing provides a straightforward, simple interface for sending in-app billing requests and managing in-app billing transactions using Android Market. This document helps you implement in-app billing by stepping through the primary implementation tasks, using the in-app billing sample application as an example.</p>
<p>Before you implement in-app billing in your own application, be sure that you read <a href="{@docRoot}guide/market/billing/billing_overview.html">Overview of In-app Billing</a> and <a href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design</a>. These documents provide background information that will make it easier for you to implement in-app billing.</p>
@@ -51,7 +47,7 @@ parent.link=index.html
<h2 id="billing-download">Downloading the Sample Application</h2>
-<p>The in-app billing sample application shows you how to perform several tasks that are common to all in-app billing implementations, including:</p>
+<p>The in-app billing sample application shows you how to perform several tasks that are common to all Android Market in-app billing implementations, including:</p>
<ul>
<li>Sending in-app billing requests to the Android Market application.</li>
@@ -64,8 +60,7 @@ parent.link=index.html
<p>The sample application includes an application file (<code>Dungeons.java</code>), the AIDL file for the <code>MarketBillingService</code> (<code>IMarketBillingService.aidl</code>), and several classes that demonstrate in-app billing messaging. It also includes a class that demonstrates basic security tasks, such as signature verification.</p>
<p>Table 1 lists the source files that are included with the sample application.</p>
-<p class="table-caption" id="source-files-table"><strong>Table 1.</strong>
-In-app billing sample application source files.</p>
+<p class="table-caption" id="source-files-table"><strong>Table 1.</strong> In-app billing sample application source files.</p>
<table>
<tr>
@@ -75,7 +70,7 @@ In-app billing sample application source files.</p>
<tr>
<td>IMarketBillingService.aidl</td>
-<td>Android Interface Definition Library (AIDL) file that defines the IPC interface to the Android Market in-app billing service (<code>MarketBillingService</code>).</td>
+<td>Android Interface Definition Library (AIDL) file that defines the IPC interface to Android Market's in-app billing service (<code>MarketBillingService</code>).</td>
</tr>
<tr>
@@ -142,7 +137,7 @@ In-app billing sample application source files.</p>
<ul>
<li>Configuring and building the sample application.</li>
<li>Uploading the sample application to Android Market.</li>
- <li>Setting up test accounts and running the sample application</li>
+ <li>Setting up test accounts and running the sample application.</li>
</ul>
<p class="note"><strong>Note:</strong> Building and running the sample application is necessary only if you want to see a demonstration of in-app billing. If you do not want to run the sample application, you can skip to the next section, <a href="#billing-add-aidl">Adding the AIDL file to your project</a>.</p>
@@ -221,7 +216,7 @@ In-app billing sample application source files.</p>
<h2 id="billing-add-aidl">Adding the AIDL file to your project</h2>
-<p>The sample application contains an Android Interface Definition Language (AIDL) file, which defines the interface to the Android Market in-app billing service <code>MarketBillingService</code>). When you add this file to your project, the Android build environment creates an interface file (<code>IMarketBillingService.java</code>). You can then use this interface to make billing requests by invoking IPC method calls.</p>
+<p>The sample application contains an Android Interface Definition Language (AIDL) file, which defines the interface to Android Market's in-app billing service (<code>MarketBillingService</code>). When you add this file to your project, the Android build environment creates an interface file (<code>IMarketBillingService.java</code>). You can then use this interface to make billing requests by invoking IPC method calls.</p>
<p>If you are using the ADT plug-in with Eclipse, you can just add this file to your <code>/src</code> directory. Eclipse will automatically generate the interface file when you build your project (which should happen immediately). If you are not using the ADT plug-in, you can put the AIDL file into your project and use the Ant tool to build your project so that the <code>IMarketBillingService.java</code> file gets generated.</p>
@@ -372,7 +367,7 @@ protected Bundle makeRequestBundle(String method) {
<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the three keys that are required for all requests: <code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The request returns a synchronous {@link android.os.Bundle} response, which contains only a single key: <code>RESPONSE_CODE</code>. The <code>RESPONSE_CODE</code> key can have the following values:</p>
<ul>
<li><code>RESULT_OK</code>&mdash;in-app billing is supported.</li>
- <li><code>RESULT_BILLING_UNAVAILABLE</code>&mdash;in-app billing is not available because the in-app billing API version you specified is not recognized or the user is not eligible to make in-app purchases (for example, the user resides in a country that prohibits in-app purchases).</li>
+ <li><code>RESULT_BILLING_UNAVAILABLE</code>&mdash;in-app billing is not available because the API version you specified is not recognized or the user is not eligible to make in-app purchases (for example, the user resides in a country that prohibits in-app purchases).</li>
<li><code>RESULT_ERROR</code>&mdash;there was an error connecting with the Android Market application.</li>
<li><code>RESULT_DEVELOPER_ERROR</code>&mdash;the application is trying to make an in-app billing request but the application has not declared the <code>com.android.vending.BILLING</code> permission in its manifest. Can also indicate that an application is not properly signed, or that you sent a malformed request.</li>
</ul>
@@ -633,7 +628,7 @@ public class BillingReceiver extends BroadcastReceiver {
<h2 id="billing-signatures">Verifying Signatures and Nonces</h2>
-<p>The in-app billing service uses two mechanisms to help verify the integrity of the transaction information you receive from Android Market: nonces and signatures. A nonce (number used once) is a cryptographically secure number that your application generates and sends with every <code>GET_PURCHASE_INFORMATION</code> and <code>RESTORE_TRANSACTIONS</code> request. The nonce is returned with the <code>PURCHASE_STATE_CHANGED</code> broadcast intent, enabling you to verify that any given <code>PURCHASE_STATE_CHANGED</code> response corresponds to an actual request that you made. Every <code>PURCHASE_STATE_CHANGED</code> broadcast intent also includes a signed JSON string and a signature, which you can use to verify the integrity of the response.</p>
+<p>Android Market's in-app billing service uses two mechanisms to help verify the integrity of the transaction information you receive from Android Market: nonces and signatures. A nonce (number used once) is a cryptographically secure number that your application generates and sends with every <code>GET_PURCHASE_INFORMATION</code> and <code>RESTORE_TRANSACTIONS</code> request. The nonce is returned with the <code>PURCHASE_STATE_CHANGED</code> broadcast intent, enabling you to verify that any given <code>PURCHASE_STATE_CHANGED</code> response corresponds to an actual request that you made. Every <code>PURCHASE_STATE_CHANGED</code> broadcast intent also includes a signed JSON string and a signature, which you can use to verify the integrity of the response.</p>
<p>Your application must provide a way to generate, manage, and verify nonces. The following sample code shows some simple methods you can use to do this.</p>
diff --git a/docs/html/guide/market/billing/billing_overview.jd b/docs/html/guide/market/billing/billing_overview.jd
index 36f9d53..feac5b0 100755
--- a/docs/html/guide/market/billing/billing_overview.jd
+++ b/docs/html/guide/market/billing/billing_overview.jd
@@ -33,11 +33,7 @@ parent.link=index.html
</div>
</div>
-<div class="special" style="margin-right:345px">
- <p>During the testing phase of the in-app billing release you cannot publish applications that implement in-app billing. You can only upload in-app billing applications as draft applications. For more information, see <a href="{@docRoot}guide/market/billing/billing_about.html">About this Release</a></p>
-</div>
-
-<p>The Android Market In-app Billing service is an Android Market feature that provides checkout processing for in-app purchases. To use the service, your application sends a billing request for a specific in-app product. The service then handles all of the checkout details for the transaction, including requesting and validating the form of payment and processing the financial transaction. When the checkout process is complete, the service sends your application the purchase details, such as the order number, the order date and time, and the price paid. At no point does your application have to handle any financial transactions; that role is provided by the in-app billing service.</p>
+<p>Android Market In-app Billing is an Android Market service that provides checkout processing for in-app purchases. To use the service, your application sends a billing request for a specific in-app product. The service then handles all of the checkout details for the transaction, including requesting and validating the form of payment and processing the financial transaction. When the checkout process is complete, the service sends your application the purchase details, such as the order number, the order date and time, and the price paid. At no point does your application have to handle any financial transactions; that role is provided by Android Market's in-app billing service.</p>
<h2 id="billing-arch">In-app Billing Architecture</h2>
@@ -53,7 +49,7 @@ parent.link=index.html
<p>A typical in-app billing implementation relies on three components:</p>
<ul>
- <li>A {@link android.app.Service} (named <code>BillingService</code> in the sample application), which processes purchase messages from the application and sends billing requests to the in-app billing service.</li>
+ <li>A {@link android.app.Service} (named <code>BillingService</code> in the sample application), which processes purchase messages from the application and sends billing requests to Android Market's in-app billing service.</li>
<li>A {@link android.content.BroadcastReceiver} (named <code>BillingReceiver</code> in the sample application), which receives all asynchronous billing responses from the Android Market application.</li>
<li>A security component (named <code>Security</code> in the sample application), which performs security-related tasks, such as signature verification and nonce generation. For more information about in-app billing security, see <a href="#billing-security">Security controls</a> later in this document.</li>
</ul>
@@ -68,7 +64,7 @@ parent.link=index.html
<h2 id="billing-msgs">In-app Billing Messages</h2>
-<p>When the user initiates a purchase, your application sends billing messages to the in-app billing service (named <code>MarketBillingService</code>) using simple IPC method calls. The Android Market application responds to all billing requests synchronously, providing your application with status notifications and other information. The Android Market application also responds to some billing requests asynchronously, providing your application with error messages and detailed transaction information. The following section describes the basic request-response messaging that takes place between your application and the Android Market application.</p>
+<p>When the user initiates a purchase, your application sends billing messages to Android Market's in-app billing service (named <code>MarketBillingService</code>) using simple IPC method calls. The Android Market application responds to all billing requests synchronously, providing your application with status notifications and other information. The Android Market application also responds to some billing requests asynchronously, providing your application with error messages and detailed transaction information. The following section describes the basic request-response messaging that takes place between your application and the Android Market application.</p>
<h3 id="billing-request">In-app billing requests</h3>
@@ -76,7 +72,7 @@ parent.link=index.html
<p>The <code>sendBillingRequest()</code> method has a single {@link android.os.Bundle} parameter. The Bundle that you deliver must include several key-value pairs that specify various parameters for the request, such as the type of billing request you are making, the item that is being purchased, and the application that is making the request. For more information about the Bundle keys that are sent with a request, see <a href="{@docRoot}guide/market/billing/billing_reference.html#billing-interface">In-app Billing Service Interface</a>.
-<p>One of the most important keys that every request Bundle must have is the <code>BILLING_REQUEST</code> key. This key lets you specify the type of billing request you are making. The in-app billing service supports the following five types of billing requests:</p>
+<p>One of the most important keys that every request Bundle must have is the <code>BILLING_REQUEST</code> key. This key lets you specify the type of billing request you are making. Android Market's in-app billing service supports the following five types of billing requests:</p>
<ul>
<li><code>CHECK_BILLING_SUPPORTED</code>
@@ -190,7 +186,7 @@ parent.link=index.html
</p>
</div>
-<p>The synchronous response for a <code>CHECK_BILLING_SUPPORTED</code> request provides a Bundle with a server response code. A <code>RESULT_OK</code> response code indicates that in-app billing is supported; a <code>RESULT_BILLING_UNAVAILABLE</code> response code indicates that in-app billing is unavailable because the in-app billing API version you specified is unrecognized or the user is not eligible to make in-app purchases (for example, the user resides in a country that does not allow in-app billing). A <code>SERVER_ERROR</code> can also be returned, indicating that there was a problem with the Android Market server.</p>
+<p>The synchronous response for a <code>CHECK_BILLING_SUPPORTED</code> request provides a Bundle with a server response code. A <code>RESULT_OK</code> response code indicates that in-app billing is supported; a <code>RESULT_BILLING_UNAVAILABLE</code> response code indicates that in-app billing is unavailable because the API version you specified is unrecognized or the user is not eligible to make in-app purchases (for example, the user resides in a country that does not allow in-app billing). A <code>SERVER_ERROR</code> can also be returned, indicating that there was a problem with the Android Market server.</p>
<h3 id="billing-action-notify">Handling IN_APP_NOTIFY messages</h3>
@@ -227,7 +223,7 @@ parent.link=index.html
<ul>
<li>In-app billing can be implemented only in applications that you publish through Android Market.</li>
- <li>You must have a Google Checkout Merchant account to use the in-app billing service.</li>
+ <li>You must have a Google Checkout Merchant account to use Android Market In-app Billing.</li>
<li>If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of the MyApps application. If your device is running any other version of Android, in-app billing requires version 2.3.4 (or higher) of the Android Market application.</li>
<li>An application can use in-app billing only if the device is running Android 1.6 (API level 4) or higher.</li>
<li>You can use in-app billing to sell only digital content. You cannot use in-app billing to sell physical goods, personal services, or anything that requires physical delivery.</li>
diff --git a/docs/html/guide/market/billing/billing_reference.jd b/docs/html/guide/market/billing/billing_reference.jd
index 744c4d1..292823d 100755
--- a/docs/html/guide/market/billing/billing_reference.jd
+++ b/docs/html/guide/market/billing/billing_reference.jd
@@ -27,10 +27,6 @@ parent.link=index.html
</div>
</div>
-<div class="special" style="margin-right:345px">
- <p>During the testing phase of the in-app billing release you cannot publish applications that implement in-app billing. You can only upload in-app billing applications as draft applications. For more information, see <a href="{@docRoot}guide/market/billing/billing_about.html">About this Release</a></p>
-</div>
-
<p>The following document provides technical reference information for the following:</p>
<ul>
@@ -84,7 +80,7 @@ parent.link=index.html
<h2 id="billing-interface">In-app Billing Service Interface</h2>
-<p>The following section describes the interface for the Android Market in-app billing service. The interface is defined in the <code>IMarketBillingService.aidl</code> file, which is included with the in-app billing <a href="{@docRoot}guide/market/billing/billing_integrate.html#billing-download">sample application</a>.</p>
+<p>The following section describes the interface for Android Market's in-app billing service. The interface is defined in the <code>IMarketBillingService.aidl</code> file, which is included with the in-app billing <a href="{@docRoot}guide/market/billing/billing_integrate.html#billing-download">sample application</a>.</p>
<p>The interface consists of a single request method <code>sendBillingRequest()</code>. This method takes a single {@link android.os.Bundle} parameter. The Bundle parameter includes several key-value pairs, which are summarized in table 2.</p>
<p class="table-caption"><strong>Table 2.</strong> Description of Bundle keys passed in a <code>sendBillingRequest()</code> request.</p>
@@ -110,7 +106,7 @@ parent.link=index.html
<td><code>int</code></td>
<td>1</td>
<td>Yes</td>
- <td>The version of the in-app billing service you are using. The current version is 1.</td>
+ <td>The version of Android Market's in-app billing service you are using. The current version is 1.</td>
</tr>
<tr>
<td><code>PACKAGE_NAME</code></td>
@@ -124,7 +120,7 @@ parent.link=index.html
<td><code>String</code></td>
<td>Any valid product identifier.</td>
<td>Required for <code>REQUEST_PURCHASE</code> requests.</td>
- <td>The product ID of the item you are making a billing request for. Every in-app item that you sell using the in-app billing service must have a unique product ID, which you specify on the Android Market publisher site.</td>
+ <td>The product ID of the item you are making a billing request for. Every in-app item that you sell using Android Market's in-app billing service must have a unique product ID, which you specify on the Android Market publisher site.</td>
</tr>
<tr>
<td><code>NONCE</code></td>
diff --git a/docs/html/guide/market/billing/billing_testing.jd b/docs/html/guide/market/billing/billing_testing.jd
index c900e8b..742e7ef 100755
--- a/docs/html/guide/market/billing/billing_testing.jd
+++ b/docs/html/guide/market/billing/billing_testing.jd
@@ -26,10 +26,6 @@ parent.link=index.html
</div>
</div>
-<div class="special" style="margin-right:345px">
- <p>During the testing phase of the in-app billing release you cannot publish applications that implement in-app billing. You can only upload in-app billing applications as draft applications. For more information, see <a href="{@docRoot}guide/market/billing/billing_about.html">About this Release</a></p>
-</div>
-
<p>The Android Market publisher site provides several tools that help you test your in-app billing implementation before it is published. You can use these tools to create test accounts and purchase special reserved items that send static billing responses to your application.</p>
<p>To test in-app billing in an application you must install the application on an Android-powered device. You cannot use the Android emulator to test in-app billing. The device you use for testing must run a standard version of the Android 1.6 or later platform (API level 4 or higher), and have the most current version of the Android Market application installed. If a device is not running the most current Android Market application, your application won't be able to send in-app billing requests to Android Market. For general information about how to set up a device for use in developing Android applications, see <a
@@ -60,7 +56,7 @@ href="{@docRoot}guide/developing/device.html">Using Hardware Devices</a>.</p>
<p>When you make an in-app billing request with this product ID Android Market responds as though the purchase was canceled. This can occur when an error is encountered in the order process, such as an invalid credit card, or when you cancel a user's order before it is charged.</p>
</li>
<li><strong>android.test.refunded</strong>
- <p>When you make an in-app billing request with this product ID, Android Market responds as though the purchase was refunded. Refunds cannot be initiated through the in-app billing feature. Refunds must be initiated by you (the merchant). A refund message is sent to your application by Android Market only when Android Market gets notification from Google Checkout that a refund has been made. For more information about refunds, see <a href="{@docRoot}guide/market/billing/billing_overview.html#billing-action-notify">Handling IN_APP_NOTIFY messages</a> and <a href="http://www.google.com/support/androidmarket/bin/answer.py?answer=1153485">In-app Billing Pricing</a>.</p>
+ <p>When you make an in-app billing request with this product ID, Android Market responds as though the purchase was refunded. Refunds cannot be initiated through Android Market's in-app billing service. Refunds must be initiated by you (the merchant). After you process a refund request through your Google Checkout account, a refund message is sent to your application by Android Market. This occurs only when Android Market gets notification from Google Checkout that a refund has been made. For more information about refunds, see <a href="{@docRoot}guide/market/billing/billing_overview.html#billing-action-notify">Handling IN_APP_NOTIFY messages</a> and <a href="http://www.google.com/support/androidmarket/bin/answer.py?answer=1153485">In-app Billing Pricing</a>.</p>
</li>
<li><strong>android.test.item_unavailable</strong>
<p>When you make an in-app billing request with this product ID, Android Market responds as though the item being purchased was not listed in your application's product list.</p>
diff --git a/docs/html/guide/market/billing/index.jd b/docs/html/guide/market/billing/index.jd
index e7f8ee3..fb85fa6 100755
--- a/docs/html/guide/market/billing/index.jd
+++ b/docs/html/guide/market/billing/index.jd
@@ -23,13 +23,9 @@ page.title=In-app Billing
</div>
</div>
-<div class="special" style="margin-right:345px">
- <p>During the testing phase of the in-app billing release you cannot publish applications that implement in-app billing. You can only upload in-app billing applications as draft applications. For more information, see <a href="{@docRoot}guide/market/billing/billing_about.html">About this Release</a></p>
-</div>
-
-<p>In-app billing is an Android Market service that lets you sell digital content in your applications. You can use the service to sell a wide range of content, including downloadable content such as media files or photos, and virtual content such as game levels or potions.</p>
+<p>Android Market In-app Billing is an Android Market service that lets you sell digital content in your applications. You can use the service to sell a wide range of content, including downloadable content such as media files or photos, and virtual content such as game levels or potions.</p>
-<p>When you use the Android Market in-app billing service to sell an item, Android Market handles all checkout details so your application never has to directly process any financial transactions. Android Market uses the same checkout service that is used for application purchases, so your users experience a consistent and familiar purchase flow (see figure 1). Also, the transaction fee for in-app purchases is the same as the transaction fee for application purchases (30%).</p>
+<p>When you use Android Market's in-app billing service to sell an item, Android Market handles all checkout details so your application never has to directly process any financial transactions. Android Market uses the same checkout service that is used for application purchases, so your users experience a consistent and familiar purchase flow (see figure 1). Also, the transaction fee for in-app purchases is the same as the transaction fee for application purchases (30%).</p>
<p>Any application that you publish through Android Market can implement in-app billing. No special account or registration is required other than an Android Market publisher account and a Google Checkout Merchant account. Also, because the service uses no dedicated framework APIs, you can add in-app billing to any application that uses a minimum API level of 4 or higher.</p>
@@ -42,7 +38,7 @@ page.title=In-app Billing
<strong>Figure 1.</strong> Applications initiate in-app billing requests through their own UI (first screen). Android Market responds to the request by providing the checkout user interface (middle screen). When checkout is complete, the application resumes.
</p>
-<p>To learn more about the in-app billing service and start integrating in-app billing into your applications, read the following documents:</p>
+<p>To learn more about Android Market's in-app billing service and start integrating it into your applications, read the following documents:</p>
<dl>
<dt><strong><a href="{@docRoot}guide/market/billing/billing_overview.html">Overview of In-app Billing</a></strong></dt>
diff --git a/docs/html/images/billing_list_form.png b/docs/html/images/billing_list_form.png
index ee30de3..de7ea22 100755
--- a/docs/html/images/billing_list_form.png
+++ b/docs/html/images/billing_list_form.png
Binary files differ
diff --git a/docs/html/images/billing_product_list.png b/docs/html/images/billing_product_list.png
index 5b8d174..49a7e79 100755
--- a/docs/html/images/billing_product_list.png
+++ b/docs/html/images/billing_product_list.png
Binary files differ
diff --git a/docs/html/images/billing_product_list_entry.png b/docs/html/images/billing_product_list_entry.png
index b7bfc7a..df3f9a8 100755
--- a/docs/html/images/billing_product_list_entry.png
+++ b/docs/html/images/billing_product_list_entry.png
Binary files differ
diff --git a/graphics/java/android/graphics/YuvImage.java b/graphics/java/android/graphics/YuvImage.java
index 9368da6..af3f276 100644
--- a/graphics/java/android/graphics/YuvImage.java
+++ b/graphics/java/android/graphics/YuvImage.java
@@ -36,7 +36,7 @@ public class YuvImage {
private final static int WORKING_COMPRESS_STORAGE = 4096;
/**
- * The YUV format as defined in {@link PixelFormat}.
+ * The YUV format as defined in {@link ImageFormat}.
*/
private int mFormat;
@@ -67,7 +67,7 @@ public class YuvImage {
*
* @param yuv The YUV data. In the case of more than one image plane, all the planes must be
* concatenated into a single byte array.
- * @param format The YUV data format as defined in {@link PixelFormat}.
+ * @param format The YUV data format as defined in {@link ImageFormat}.
* @param width The width of the YuvImage.
* @param height The height of the YuvImage.
* @param strides (Optional) Row bytes of each image plane. If yuv contains padding, the stride
@@ -152,7 +152,7 @@ public class YuvImage {
}
/**
- * @return the YUV format as defined in {@link PixelFormat}.
+ * @return the YUV format as defined in {@link ImageFormat}.
*/
public int getYuvFormat() {
return mFormat;
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index f3c8f64..3c6dccc 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -219,12 +219,6 @@ public:
// send command to camera driver
status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
- // return the total number of available video buffers.
- int32_t getNumberOfVideoBuffers() const;
-
- // return the individual video buffer corresponding to the given index.
- sp<IMemory> getVideoBuffer(int32_t index) const;
-
// tell camera hal to store meta data or real YUV in video buffers.
status_t storeMetaDataInBuffers(bool enabled);
diff --git a/include/camera/CameraHardwareInterface.h b/include/camera/CameraHardwareInterface.h
index 86bd849..3f34120 100644
--- a/include/camera/CameraHardwareInterface.h
+++ b/include/camera/CameraHardwareInterface.h
@@ -28,16 +28,6 @@
namespace android {
-/**
- * The size of image for display.
- */
-typedef struct image_rect_struct
-{
- uint32_t width; /* Image width */
- uint32_t height; /* Image height */
-} image_rect_type;
-
-
typedef void (*notify_callback)(int32_t msgType,
int32_t ext1,
int32_t ext2,
@@ -90,9 +80,6 @@ public:
/** Set the ANativeWindow to which preview frames are sent */
virtual status_t setPreviewWindow(const sp<ANativeWindow>& buf) = 0;
- /** Return the IMemoryHeap for the raw image heap */
- virtual sp<IMemoryHeap> getRawHeap() const = 0;
-
/** Set the notification and data callbacks */
virtual void setCallbacks(notify_callback notify_cb,
data_callback data_cb,
@@ -145,47 +132,6 @@ public:
virtual bool previewEnabled() = 0;
/**
- * Retrieve the total number of available buffers from camera hal for passing
- * video frame data in a recording session. Must be called again if a new
- * recording session is started.
- *
- * This method should be called after startRecording(), since
- * the some camera hal may choose to allocate the video buffers only after
- * recording is started.
- *
- * Some camera hal may not implement this method, and 0 can be returned to
- * indicate that this feature is not available.
- *
- * @return the number of video buffers that camera hal makes available.
- * Zero (0) is returned to indicate that camera hal does not support
- * this feature.
- */
- virtual int32_t getNumberOfVideoBuffers() const { return 0; }
-
- /**
- * Retrieve the video buffer corresponding to the given index in a
- * recording session. Must be called again if a new recording session
- * is started.
- *
- * It allows a client to retrieve all video buffers that camera hal makes
- * available to passing video frame data by calling this method with all
- * valid index values. The valid index value ranges from 0 to n, where
- * n = getNumberOfVideoBuffers() - 1. With an index outside of the valid
- * range, 0 must be returned. This method should be called after
- * startRecording().
- *
- * The video buffers should NOT be modified/released by camera hal
- * until stopRecording() is called and all outstanding video buffers
- * previously sent out via CAMERA_MSG_VIDEO_FRAME have been released
- * via releaseVideoBuffer().
- *
- * @param index an index to retrieve the corresponding video buffer.
- *
- * @return the video buffer corresponding to the given index.
- */
- virtual sp<IMemory> getVideoBuffer(int32_t index) const { return 0; }
-
- /**
* Request the camera hal to store meta data or real YUV data in
* the video buffers send out via CAMERA_MSG_VIDEO_FRRAME for a
* recording session. If it is not called, the default camera
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
index 2344b3f..400d7f4 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/ICamera.h
@@ -102,12 +102,6 @@ public:
// send command to camera driver
virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
- // return the total number of available video buffers
- virtual int32_t getNumberOfVideoBuffers() const = 0;
-
- // return the individual video buffer corresponding to the given index.
- virtual sp<IMemory> getVideoBuffer(int32_t index) const = 0;
-
// tell the camera hal to store meta data or real YUV data in video buffers.
virtual status_t storeMetaDataInBuffers(bool enabled) = 0;
};
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 4a39fbf..bb25bae 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -99,34 +99,6 @@ public:
virtual sp<MetaData> getFormat();
/**
- * Retrieve the total number of video buffers available from
- * this source.
- *
- * This method is useful if these video buffers are used
- * for passing video frame data to other media components,
- * such as OMX video encoders, in order to eliminate the
- * memcpy of the data.
- *
- * @return the total numbner of video buffers. Returns 0 to
- * indicate that this source does not make the video
- * buffer information availalble.
- */
- size_t getNumberOfVideoBuffers() const;
-
- /**
- * Retrieve the individual video buffer available from
- * this source.
- *
- * @param index the index corresponding to the video buffer.
- * Valid range of the index is [0, n], where n =
- * getNumberOfVideoBuffers() - 1.
- *
- * @return the video buffer corresponding to the given index.
- * If index is out of range, 0 should be returned.
- */
- sp<IMemory> getVideoBuffer(size_t index) const;
-
- /**
* Tell whether this camera source stores meta data or real YUV
* frame data in video buffers.
*
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp
index e288312..5eb48da 100644
--- a/libs/camera/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -205,22 +205,6 @@ status_t Camera::startPreview()
return c->startPreview();
}
-int32_t Camera::getNumberOfVideoBuffers() const
-{
- LOGV("getNumberOfVideoBuffers");
- sp <ICamera> c = mCamera;
- if (c == 0) return 0;
- return c->getNumberOfVideoBuffers();
-}
-
-sp<IMemory> Camera::getVideoBuffer(int32_t index) const
-{
- LOGV("getVideoBuffer: %d", index);
- sp <ICamera> c = mCamera;
- if (c == 0) return 0;
- return c->getVideoBuffer(index);
-}
-
status_t Camera::storeMetaDataInBuffers(bool enabled)
{
LOGV("storeMetaDataInBuffers: %s",
diff --git a/libs/camera/ICamera.cpp b/libs/camera/ICamera.cpp
index 931b57d..5f6e5ef 100644
--- a/libs/camera/ICamera.cpp
+++ b/libs/camera/ICamera.cpp
@@ -46,8 +46,6 @@ enum {
STOP_RECORDING,
RECORDING_ENABLED,
RELEASE_RECORDING_FRAME,
- GET_NUM_VIDEO_BUFFERS,
- GET_VIDEO_BUFFER,
STORE_META_DATA_IN_BUFFERS,
};
@@ -149,27 +147,6 @@ public:
remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
}
- int32_t getNumberOfVideoBuffers() const
- {
- LOGV("getNumberOfVideoBuffers");
- Parcel data, reply;
- data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
- remote()->transact(GET_NUM_VIDEO_BUFFERS, data, &reply);
- return reply.readInt32();
- }
-
- sp<IMemory> getVideoBuffer(int32_t index) const
- {
- LOGV("getVideoBuffer: %d", index);
- Parcel data, reply;
- data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
- data.writeInt32(index);
- remote()->transact(GET_VIDEO_BUFFER, data, &reply);
- sp<IMemory> mem = interface_cast<IMemory>(
- reply.readStrongBinder());
- return mem;
- }
-
status_t storeMetaDataInBuffers(bool enabled)
{
LOGV("storeMetaDataInBuffers: %s", enabled? "true": "false");
@@ -355,19 +332,6 @@ status_t BnCamera::onTransact(
releaseRecordingFrame(mem);
return NO_ERROR;
} break;
- case GET_NUM_VIDEO_BUFFERS: {
- LOGV("GET_NUM_VIDEO_BUFFERS");
- CHECK_INTERFACE(ICamera, data, reply);
- reply->writeInt32(getNumberOfVideoBuffers());
- return NO_ERROR;
- } break;
- case GET_VIDEO_BUFFER: {
- LOGV("GET_VIDEO_BUFFER");
- CHECK_INTERFACE(ICamera, data, reply);
- int32_t index = data.readInt32();
- reply->writeStrongBinder(getVideoBuffer(index)->asBinder());
- return NO_ERROR;
- } break;
case STORE_META_DATA_IN_BUFFERS: {
LOGV("STORE_META_DATA_IN_BUFFERS");
CHECK_INTERFACE(ICamera, data, reply);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 9aa84a03..cc689bb 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -715,15 +715,13 @@ public class LocationManager {
}
/**
- * Registers the current activity to be notified periodically by
- * the named provider. Periodically, the supplied LocationListener will
- * be called with the current Location or with status updates.
+ * Requests a single location update from the named provider.
*
* <p> It may take a while to receive the most recent location. If
* an immediate location is required, applications may use the
* {@link #getLastKnownLocation(String)} method.
*
- * <p> In case the provider is disabled by the user, updates will stop,
+ * <p> In case the provider is disabled by the user, the update will not be received,
* and the {@link LocationListener#onProviderDisabled(String)}
* method will be called. As soon as the provider is enabled again,
* the {@link LocationListener#onProviderEnabled(String)} method will
@@ -733,8 +731,8 @@ public class LocationManager {
*
* @param provider the name of the provider with which to register
* @param listener a {#link LocationListener} whose
- * {@link LocationListener#onLocationChanged} method will be called for
- * each location update
+ * {@link LocationListener#onLocationChanged} method will be called when
+ * the location update is available
* @param looper a Looper object whose message queue will be used to
* implement the callback mechanism.
* If looper is null then the callbacks will be called on the main thread.
@@ -754,15 +752,13 @@ public class LocationManager {
}
/**
- * Registers the current activity to be notified periodically based on
- * the specified criteria. Periodically, the supplied LocationListener will
- * be called with the current Location or with status updates.
+ * Requests a single location update based on the specified criteria.
*
* <p> It may take a while to receive the most recent location. If
* an immediate location is required, applications may use the
* {@link #getLastKnownLocation(String)} method.
*
- * <p> In case the provider is disabled by the user, updates will stop,
+ * <p> In case the provider is disabled by the user, the update will not be received,
* and the {@link LocationListener#onProviderDisabled(String)}
* method will be called. As soon as the provider is enabled again,
* the {@link LocationListener#onProviderEnabled(String)} method will
@@ -773,8 +769,8 @@ public class LocationManager {
* @param criteria contains parameters for the location manager to choose the
* appropriate provider and parameters to compute the location
* @param listener a {#link LocationListener} whose
- * {@link LocationListener#onLocationChanged} method will be called for
- * each location update
+ * {@link LocationListener#onLocationChanged} method will be called when
+ * the location update is available
* @param looper a Looper object whose message queue will be used to
* implement the callback mechanism.
* If looper is null then the callbacks will be called on the current thread.
@@ -795,16 +791,20 @@ public class LocationManager {
}
/**
- * Registers the current activity to be notified periodically by
- * the named provider. Periodically, the supplied PendingIntent will
- * be broadcast with the current Location or with status updates.
- *
- * <p> Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value.
+ * Requests a single location update from the named provider.
*
* <p> It may take a while to receive the most recent location. If
* an immediate location is required, applications may use the
* {@link #getLastKnownLocation(String)} method.
*
+ * <p> Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value.
+ *
+ * <p> In case the provider is disabled by the user, the update will not be received,
+ * and the {@link LocationListener#onProviderDisabled(String)}
+ * method will be called. As soon as the provider is enabled again,
+ * the {@link LocationListener#onProviderEnabled(String)} method will
+ * be called and location updates will start again.
+ *
* @param provider the name of the provider with which to register
* @param intent a {#link PendingIntent} to be sent for the location update
*
@@ -823,16 +823,20 @@ public class LocationManager {
}
/**
- * Registers the current activity to be notified periodically based on
- * the specified criteria. Periodically, the supplied PendingIntent will
- * be broadcast with the current Location or with status updates.
- *
- * <p> Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value.
+ * Requests a single location update based on the specified criteria.
*
* <p> It may take a while to receive the most recent location. If
* an immediate location is required, applications may use the
* {@link #getLastKnownLocation(String)} method.
*
+ * <p> Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value.
+ *
+ * <p> In case the provider is disabled by the user, the update will not be received,
+ * and the {@link LocationListener#onProviderDisabled(String)}
+ * method will be called. As soon as the provider is enabled again,
+ * the {@link LocationListener#onProviderEnabled(String)} method will
+ * be called and location updates will start again.
+ *
* @param criteria contains parameters for the location manager to choose the
* appropriate provider and parameters to compute the location
* @param intent a {#link PendingIntent} to be sent for the location update
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index a027bc6..c41e0ad 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -185,6 +185,7 @@ public class MediaFile {
addFileType("IMY", FILE_TYPE_IMY, "audio/imelody");
addFileType("RTX", FILE_TYPE_MID, "audio/midi");
addFileType("OTA", FILE_TYPE_MID, "audio/midi");
+ addFileType("MXMF", FILE_TYPE_MID, "audio/midi");
addFileType("MPEG", FILE_TYPE_MP4, "video/mpeg", MtpConstants.FORMAT_MPEG);
addFileType("MPG", FILE_TYPE_MP4, "video/mpeg", MtpConstants.FORMAT_MPEG);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index fcbe59e..e2dee00 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1616,10 +1616,12 @@ public class MediaPlayer
/** MediaPlayer is temporarily pausing playback internally in order to
* buffer more data.
+ * @see android.media.MediaPlayer.OnInfoListener
*/
public static final int MEDIA_INFO_BUFFERING_START = 701;
/** MediaPlayer is resuming playback after filling buffers.
+ * @see android.media.MediaPlayer.OnInfoListener
*/
public static final int MEDIA_INFO_BUFFERING_END = 702;
@@ -1654,6 +1656,8 @@ public class MediaPlayer
* <ul>
* <li>{@link #MEDIA_INFO_UNKNOWN}
* <li>{@link #MEDIA_INFO_VIDEO_TRACK_LAGGING}
+ * <li>{@link #MEDIA_INFO_BUFFERING_START}
+ * <li>{@link #MEDIA_INFO_BUFFERING_END}
* <li>{@link #MEDIA_INFO_BAD_INTERLEAVING}
* <li>{@link #MEDIA_INFO_NOT_SEEKABLE}
* <li>{@link #MEDIA_INFO_METADATA_UPDATE}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 6b9f2fb..02f3902 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -347,7 +347,6 @@ public class MediaScanner
private BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
private static class FileCacheEntry {
- Uri mTableUri;
long mRowId;
String mPath;
long mLastModified;
@@ -355,8 +354,7 @@ public class MediaScanner
boolean mSeenInFileSystem;
boolean mLastModifiedChanged;
- FileCacheEntry(Uri tableUri, long rowId, String path, long lastModified, int format) {
- mTableUri = tableUri;
+ FileCacheEntry(long rowId, String path, long lastModified, int format) {
mRowId = rowId;
mPath = path;
mLastModified = lastModified;
@@ -367,7 +365,7 @@ public class MediaScanner
@Override
public String toString() {
- return mPath + " mTableUri: " + mTableUri + " mRowId: " + mRowId;
+ return mPath + " mRowId: " + mRowId;
}
}
@@ -491,23 +489,10 @@ public class MediaScanner
long delta = (entry != null) ? (lastModified - entry.mLastModified) : 0;
boolean wasModified = delta > 1 || delta < -1;
if (entry == null || wasModified) {
- Uri tableUri;
- if (isDirectory) {
- tableUri = mFilesUri;
- } else if (MediaFile.isVideoFileType(mFileType)) {
- tableUri = mVideoUri;
- } else if (MediaFile.isImageFileType(mFileType)) {
- tableUri = mImagesUri;
- } else if (MediaFile.isAudioFileType(mFileType)) {
- tableUri = mAudioUri;
- } else {
- tableUri = mFilesUri;
- }
if (wasModified) {
entry.mLastModified = lastModified;
- entry.mTableUri = tableUri;
} else {
- entry = new FileCacheEntry(tableUri, 0, path, lastModified,
+ entry = new FileCacheEntry(0, path, lastModified,
(isDirectory ? MtpConstants.FORMAT_ASSOCIATION : 0));
mFileCache.put(key, entry);
}
@@ -829,7 +814,14 @@ public class MediaScanner
}
}
- Uri tableUri = entry.mTableUri;
+ Uri tableUri = mFilesUri;
+ if (MediaFile.isVideoFileType(mFileType)) {
+ tableUri = mVideoUri;
+ } else if (MediaFile.isImageFileType(mFileType)) {
+ tableUri = mImagesUri;
+ } else if (MediaFile.isAudioFileType(mFileType)) {
+ tableUri = mAudioUri;
+ }
Uri result = null;
if (rowId == 0) {
if (mMtpObjectHandle != 0) {
@@ -1021,13 +1013,13 @@ public class MediaScanner
// Only consider entries with absolute path names.
// This allows storing URIs in the database without the
// media scanner removing them.
- if (path.startsWith("/")) {
+ if (path != null && path.startsWith("/")) {
String key = path;
if (mCaseInsensitivePaths) {
key = path.toLowerCase();
}
- FileCacheEntry entry = new FileCacheEntry(mFilesUri, rowId, path,
+ FileCacheEntry entry = new FileCacheEntry(rowId, path,
lastModified, format);
mFileCache.put(key, entry);
}
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 8a24bc4..a1f04d3 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -740,28 +740,6 @@ void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
mFrameAvailableCondition.signal();
}
-size_t CameraSource::getNumberOfVideoBuffers() const {
- LOGV("getNumberOfVideoBuffers");
- size_t nBuffers = 0;
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- if (mInitCheck == OK && mCamera != 0) {
- nBuffers = mCamera->getNumberOfVideoBuffers();
- }
- IPCThreadState::self()->restoreCallingIdentity(token);
- return nBuffers;
-}
-
-sp<IMemory> CameraSource::getVideoBuffer(size_t index) const {
- LOGV("getVideoBuffer: %d", index);
- sp<IMemory> buffer = 0;
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- if (mInitCheck == OK && mCamera != 0) {
- buffer = mCamera->getVideoBuffer(index);
- }
- IPCThreadState::self()->restoreCallingIdentity(token);
- return buffer;
-}
-
bool CameraSource::isMetaDataStoredInVideoBuffers() const {
LOGV("isMetaDataStoredInVideoBuffers");
return mIsMetaDataStoredInVideoBuffers;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index a6a34b3..904bd62 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1912,6 +1912,11 @@ OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
}
void OMXCodec::on_message(const omx_message &msg) {
+ if (mState == ERROR) {
+ LOGW("Dropping OMX message - we're in ERROR state.");
+ return;
+ }
+
switch (msg.type) {
case omx_message::EVENT:
{
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 84f65ff..8b86e53 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -37,7 +37,7 @@ static bool FileHasAcceptableExtension(const char *extension) {
".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
- ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac"
+ ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
};
static const size_t kNumValidExtensions =
sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
@@ -124,7 +124,8 @@ status_t StagefrightMediaScanner::processFile(
|| !strcasecmp(extension, ".xmf")
|| !strcasecmp(extension, ".rtttl")
|| !strcasecmp(extension, ".rtx")
- || !strcasecmp(extension, ".ota")) {
+ || !strcasecmp(extension, ".ota")
+ || !strcasecmp(extension, ".mxmf")) {
status_t status = HandleMIDI(path, &client);
if (status != OK) {
return status;
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index b7087f8..a5b316d 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -33,18 +33,30 @@ ALooperRoster gLooperRoster;
struct ALooper::LooperThread : public Thread {
LooperThread(ALooper *looper, bool canCallJava)
: Thread(canCallJava),
- mLooper(looper) {
+ mLooper(looper),
+ mThreadId(NULL) {
+ }
+
+ virtual status_t readyToRun() {
+ mThreadId = androidGetThreadId();
+
+ return Thread::readyToRun();
}
virtual bool threadLoop() {
return mLooper->loop();
}
+ bool isCurrentThread() const {
+ return mThreadId == androidGetThreadId();
+ }
+
protected:
virtual ~LooperThread() {}
private:
ALooper *mLooper;
+ android_thread_id_t mThreadId;
DISALLOW_EVIL_CONSTRUCTORS(LooperThread);
};
@@ -136,7 +148,9 @@ status_t ALooper::stop() {
mQueueChangedCondition.signal();
- if (!runningLocally) {
+ if (!runningLocally && !thread->isCurrentThread()) {
+ // If not running locally and this thread _is_ the looper thread,
+ // the loop() function will return and never be called again.
thread->requestExitAndWait();
}
@@ -197,6 +211,11 @@ bool ALooper::loop() {
gLooperRoster.deliverMessage(event.mMessage);
+ // NOTE: It's important to note that at this point our "ALooper" object
+ // may no longer exist (its final reference may have gone away while
+ // delivering the message). We have made sure, however, that loop()
+ // won't be called again.
+
return true;
}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 6cbd599..cdce772 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#define LOG_TAG "OMXNodeInstance"
#include <utils/Log.h>
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 0740515..c4e0cdc 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -20,6 +20,8 @@
#include "ARTSPConnection.h"
+#include <cutils/properties.h>
+
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -44,6 +46,7 @@ ARTSPConnection::ARTSPConnection()
mConnectionID(0),
mNextCSeq(0),
mReceiveResponseEventPending(false) {
+ MakeUserAgent(&mUserAgent);
}
ARTSPConnection::~ARTSPConnection() {
@@ -378,6 +381,7 @@ void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
reply->setString("original-request", request.c_str(), request.size());
addAuthentication(&request);
+ addUserAgent(&request);
// Find the boundary between headers and the body.
ssize_t i = request.find("\r\n\r\n");
@@ -979,4 +983,27 @@ void ARTSPConnection::addAuthentication(AString *request) {
#endif
}
+// static
+void ARTSPConnection::MakeUserAgent(AString *userAgent) {
+ userAgent->clear();
+ userAgent->setTo("User-Agent: stagefright/1.1 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.build.version.release", value, "Unknown");
+ userAgent->append(value);
+ userAgent->append(")\r\n");
+}
+
+void ARTSPConnection::addUserAgent(AString *request) const {
+ // Find the boundary between headers and the body.
+ ssize_t i = request->find("\r\n\r\n");
+ CHECK_GE(i, 0);
+
+ request->insert(mUserAgent, i + 2);
+}
+
} // namespace android
diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h
index 0fecf3c..ac2e3ae 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.h
+++ b/media/libstagefright/rtsp/ARTSPConnection.h
@@ -87,6 +87,8 @@ private:
sp<AMessage> mObserveBinaryMessage;
+ AString mUserAgent;
+
void onConnect(const sp<AMessage> &msg);
void onDisconnect(const sp<AMessage> &msg);
void onCompleteConnection(const sp<AMessage> &msg);
@@ -106,6 +108,8 @@ private:
bool parseAuthMethod(const sp<ARTSPResponse> &response);
void addAuthentication(AString *request);
+ void addUserAgent(AString *request) const;
+
status_t findPendingRequest(
const sp<ARTSPResponse> &response, ssize_t *index) const;
@@ -114,6 +118,8 @@ private:
static bool ParseSingleUnsignedLong(
const char *from, unsigned long *x);
+ static void MakeUserAgent(AString *userAgent);
+
DISALLOW_EVIL_CONSTRUCTORS(ARTSPConnection);
};
diff --git a/opengl/libs/GLES2_dbg/src/api.h b/opengl/libs/GLES2_dbg/src/api.h
index 93aef62..b9fc341 100644
--- a/opengl/libs/GLES2_dbg/src/api.h
+++ b/opengl/libs/GLES2_dbg/src/api.h
@@ -22,8 +22,7 @@
unsigned readSize = GetBytesPerPixel(readFormat, readType) * width * height; \
void * readData = dbg->GetReadPixelsBuffer(readSize); \
dbg->hooks->gl.glReadPixels(x, y, width, height, readFormat, readType, readData); \
- const unsigned compressedSize = dbg->CompressReadPixelBuffer(); \
- msg.set_data(dbg->lzf_buf, compressedSize); \
+ dbg->CompressReadPixelBuffer(msg.mutable_data()); \
msg.set_data_type(msg.ReferencedImage); \
msg.set_pixel_format(readFormat); \
msg.set_pixel_type(readType);
@@ -43,8 +42,7 @@
DbgContext * const dbg = getDbgContextThreadSpecific(); \
const unsigned size = GetBytesPerPixel(format, type) * width * height; \
assert(0 < size); \
- unsigned compressedSize = dbg->Compress(pixels, size); \
- msg.set_data(dbg->lzf_buf, compressedSize); \
+ dbg->Compress(pixels, size, msg.mutable_data()); \
}
#define EXTEND_Debug_glTexSubImage2D EXTEND_Debug_glTexImage2D
diff --git a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
index 3ef0752..cc7336c 100644
--- a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
+++ b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
@@ -26,8 +26,7 @@ namespace android
DbgContext::DbgContext(const unsigned version, const gl_hooks_t * const hooks,
const unsigned MAX_VERTEX_ATTRIBS)
- : lzf_buf(NULL), lzf_bufSize(0)
- , lzf_readIndex(0), lzf_refSize(0), lzf_refBufSize(0)
+ : lzf_buf(NULL), lzf_readIndex(0), lzf_refSize(0), lzf_refBufSize(0)
, version(version), hooks(hooks)
, MAX_VERTEX_ATTRIBS(MAX_VERTEX_ATTRIBS)
, vertexAttribs(new VertexAttrib[MAX_VERTEX_ATTRIBS])
@@ -109,16 +108,26 @@ void DbgContext::Fetch(const unsigned index, std::string * const data) const
}
}
-unsigned DbgContext::Compress(const void * in_data, unsigned in_len)
+void DbgContext::Compress(const void * in_data, unsigned int in_len,
+ std::string * const outStr)
{
- if (lzf_bufSize < in_len * 1.05f) {
- lzf_bufSize = in_len * 1.05f;
- lzf_buf = (char *)realloc(lzf_buf, lzf_bufSize);
+ if (!lzf_buf)
+ lzf_buf = (char *)malloc(LZF_CHUNK_SIZE);
+ const uint32_t totalDecompSize = in_len;
+ outStr->append((const char *)&totalDecompSize, sizeof(totalDecompSize));
+ for (unsigned int i = 0; i < in_len; i += LZF_CHUNK_SIZE) {
+ uint32_t chunkSize = LZF_CHUNK_SIZE;
+ if (i + LZF_CHUNK_SIZE > in_len)
+ chunkSize = in_len - i;
+ const uint32_t compSize = lzf_compress((const char *)in_data + i, chunkSize,
+ lzf_buf, LZF_CHUNK_SIZE);
+ outStr->append((const char *)&chunkSize, sizeof(chunkSize));
+ outStr->append((const char *)&compSize, sizeof(compSize));
+ if (compSize > 0)
+ outStr->append(lzf_buf, compSize);
+ else // compressed chunk bigger than LZF_CHUNK_SIZE (and uncompressed)
+ outStr->append((const char *)in_data + i, chunkSize);
}
- unsigned compressedSize = lzf_compress((const char *)in_data,
- in_len, lzf_buf, lzf_bufSize);
- assert (0 < compressedSize);
- return compressedSize;
}
void * DbgContext::GetReadPixelsBuffer(const unsigned size)
@@ -140,13 +149,13 @@ void * DbgContext::GetReadPixelsBuffer(const unsigned size)
return lzf_ref[lzf_readIndex];
}
-unsigned DbgContext::CompressReadPixelBuffer()
+void DbgContext::CompressReadPixelBuffer(std::string * const outStr)
{
unsigned * const ref = lzf_ref[lzf_readIndex ^ 1];
unsigned * const src = lzf_ref[lzf_readIndex];
for (unsigned i = 0; i < lzf_refSize / sizeof(*ref) + 1; i++)
ref[i] ^= src[i];
- return Compress(ref, lzf_refSize);
+ Compress(ref, lzf_refSize, outStr);
}
void DbgContext::glUseProgram(GLuint program)
diff --git a/opengl/libs/GLES2_dbg/src/header.h b/opengl/libs/GLES2_dbg/src/header.h
index 7e9aa4e..9218da5 100644
--- a/opengl/libs/GLES2_dbg/src/header.h
+++ b/opengl/libs/GLES2_dbg/src/header.h
@@ -56,21 +56,18 @@ using namespace com::android;
namespace android
{
-struct GLFunctionBitfield
-{
+struct GLFunctionBitfield {
unsigned char field [24]; // 8 * 24 = 192
-
- void Bit(const glesv2debugger::Message_Function function, bool bit)
- {
+
+ void Bit(const glesv2debugger::Message_Function function, bool bit) {
const unsigned byte = function / 8, mask = 1 << (function % 8);
if (bit)
field[byte] |= mask;
else
field[byte] &= ~mask;
}
-
- bool Bit(const glesv2debugger::Message_Function function) const
- {
+
+ bool Bit(const glesv2debugger::Message_Function function) const {
const unsigned byte = function / 8, mask = 1 << (function % 8);
return field[byte] & mask;
}
@@ -78,7 +75,8 @@ struct GLFunctionBitfield
struct DbgContext {
private:
- unsigned lzf_bufSize;
+ static const unsigned int LZF_CHUNK_SIZE = 256 * 1024;
+ char * lzf_buf; // malloc / free; for lzf chunk compression
// used as buffer and reference frame for ReadPixels; malloc/free
unsigned * lzf_ref [2];
@@ -86,14 +84,12 @@ private:
unsigned lzf_refSize, lzf_refBufSize; // bytes
public:
- char * lzf_buf; // auto malloc/free; output of lzf_compress
-
const unsigned version; // 0 is GLES1, 1 is GLES2
const gl_hooks_t * const hooks;
const unsigned MAX_VERTEX_ATTRIBS;
-
+
GLFunctionBitfield expectResponse;
-
+
struct VertexAttrib {
GLenum type; // element data type
unsigned size; // number of data per element
@@ -122,21 +118,23 @@ public:
GLuint program;
unsigned maxAttrib; // number of slots used by program
- DbgContext(const unsigned version, const gl_hooks_t * const hooks, const unsigned MAX_VERTEX_ATTRIBS);
+ DbgContext(const unsigned version, const gl_hooks_t * const hooks,
+ const unsigned MAX_VERTEX_ATTRIBS);
~DbgContext();
void Fetch(const unsigned index, std::string * const data) const;
- unsigned Compress(const void * in_data, unsigned in_len); // compressed to lzf_buf
+ void Compress(const void * in_data, unsigned in_len, std::string * const outStr);
void * GetReadPixelsBuffer(const unsigned size);
bool IsReadPixelBuffer(const void * const ptr) {
return ptr == lzf_ref[lzf_readIndex];
}
- unsigned CompressReadPixelBuffer();
+ void CompressReadPixelBuffer(std::string * const outStr);
void glUseProgram(GLuint program);
void glEnableVertexAttribArray(GLuint index);
void glDisableVertexAttribArray(GLuint index);
- void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+ void glVertexAttribPointer(GLuint indx, GLint size, GLenum type,
+ GLboolean normalized, GLsizei stride, const GLvoid* ptr);
void glBindBuffer(GLenum target, GLuint buffer);
void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
@@ -148,7 +146,8 @@ DbgContext * getDbgContextThreadSpecific();
#define DBGCONTEXT(ctx) DbgContext * const ctx = getDbgContextThreadSpecific();
struct FunctionCall {
- virtual const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) = 0;
+ virtual const int * operator()(gl_hooks_t::gl_t const * const _c,
+ glesv2debugger::Message & msg) = 0;
virtual ~FunctionCall() {}
};
@@ -168,5 +167,5 @@ void Receive(glesv2debugger::Message & cmd);
float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd);
void SetProp(DbgContext * const dbg, const glesv2debugger::Message & cmd);
const int * GenerateCall(DbgContext * const dbg, const glesv2debugger::Message & cmd,
- glesv2debugger::Message & msg, const int * const prevRet);
+ glesv2debugger::Message & msg, const int * const prevRet);
}; // namespace android {
diff --git a/opengl/libs/GLES2_dbg/src/vertex.cpp b/opengl/libs/GLES2_dbg/src/vertex.cpp
index a9cf9e7..471e5ad 100644
--- a/opengl/libs/GLES2_dbg/src/vertex.cpp
+++ b/opengl/libs/GLES2_dbg/src/vertex.cpp
@@ -39,7 +39,6 @@ void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
msg.set_arg6(reinterpret_cast<int>(pixels));
const unsigned size = width * height * GetBytesPerPixel(format, type);
- unsigned compressed = 0;
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
Send(msg, cmd);
@@ -56,13 +55,12 @@ void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
msg.set_type(glesv2debugger::Message_Type_AfterCall);
msg.set_expect_response(expectResponse);
if (dbg->IsReadPixelBuffer(pixels)) {
- compressed = dbg->CompressReadPixelBuffer();
+ dbg->CompressReadPixelBuffer(msg.mutable_data());
msg.set_data_type(msg.ReferencedImage);
} else {
- compressed = dbg->Compress(pixels, size);
+ dbg->Compress(pixels, size, msg.mutable_data());
msg.set_data_type(msg.NonreferencedImage);
}
- msg.set_data(dbg->lzf_buf, compressed);
if (!expectResponse)
cmd.set_function(glesv2debugger::Message_Function_SKIP);
Send(msg, cmd);
diff --git a/opengl/tests/gl2_cameraeye/Android.mk b/opengl/tests/gl2_cameraeye/Android.mk
new file mode 100644
index 0000000..4a43a9e
--- /dev/null
+++ b/opengl/tests/gl2_cameraeye/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := GL2CameraEye
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/opengl/tests/gl2_cameraeye/AndroidManifest.xml b/opengl/tests/gl2_cameraeye/AndroidManifest.xml
new file mode 100644
index 0000000..c53f7be
--- /dev/null
+++ b/opengl/tests/gl2_cameraeye/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Declare the contents of this Android application. The namespace
+ attribute brings in the Android platform namespace, and the package
+ supplies a unique name for the application. When writing your
+ own application, the package name must be changed from "com.example.*"
+ to come from a domain that you own or have control over. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.gl2cameraeye">
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-feature android:name="android.hardware.camera" />
+ <uses-feature android:name="android.hardware.camera.autofocus" />
+ <uses-feature android:glEsVersion="0x00020000" />
+ <application android:label="@string/gl2cameraeye_name">
+ <activity android:name="GL2CameraEye">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/opengl/tests/gl2_cameraeye/res/values/strings.xml b/opengl/tests/gl2_cameraeye/res/values/strings.xml
new file mode 100644
index 0000000..386b930
--- /dev/null
+++ b/opengl/tests/gl2_cameraeye/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+
+ <string name="gl2cameraeye_name">GL2CameraEye</string>
+
+</resources>
diff --git a/opengl/tests/gl2_cameraeye/src/com/android/gl2cameraeye/GL2CameraEye.java b/opengl/tests/gl2_cameraeye/src/com/android/gl2cameraeye/GL2CameraEye.java
new file mode 100644
index 0000000..561e4c5
--- /dev/null
+++ b/opengl/tests/gl2_cameraeye/src/com/android/gl2cameraeye/GL2CameraEye.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gl2cameraeye;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.app.Activity;
+import android.content.pm.ActivityInfo;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.content.Context;
+import android.util.Log;
+
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLUtils;
+import android.opengl.Matrix;
+
+import android.graphics.SurfaceTexture;
+
+import android.hardware.Camera;
+import android.hardware.SensorManager;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.Sensor;
+
+public class GL2CameraEye extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mGLView = new CamGLSurfaceView(this);
+ setContentView(mGLView);
+ setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mGLView.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGLView.onResume();
+ }
+
+ private GLSurfaceView mGLView;
+}
+
+class CamGLSurfaceView extends GLSurfaceView implements SensorEventListener {
+ public CamGLSurfaceView(Context context) {
+ super(context);
+ setEGLContextClientVersion(2);
+ mRenderer = new CamRenderer(context);
+ setRenderer(mRenderer);
+
+ mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
+ mAcceleration = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
+ }
+
+ public boolean onTouchEvent(final MotionEvent event) {
+ queueEvent(new Runnable(){
+ public void run() {
+ mRenderer.setPosition(event.getX() / getWidth(),
+ event.getY() / getHeight());
+ }});
+ return true;
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mCamera.stopPreview();
+ mCamera.release();
+
+ mSensorManager.unregisterListener(this);
+ }
+
+ @Override
+ public void onResume() {
+ mCamera = Camera.open();
+ Camera.Parameters p = mCamera.getParameters();
+ // No changes to default camera parameters
+ mCamera.setParameters(p);
+
+ queueEvent(new Runnable(){
+ public void run() {
+ mRenderer.setCamera(mCamera);
+ }});
+
+ mSensorManager.registerListener(this, mAcceleration, SensorManager.SENSOR_DELAY_GAME);
+ super.onResume();
+ }
+
+ public void onSensorChanged(SensorEvent event) {
+ if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {
+ final float[] accelerationVector = event.values;
+ queueEvent(new Runnable(){
+ public void run() {
+ mRenderer.setAcceleration(accelerationVector);
+ }});
+ }
+ }
+
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ // Ignoring sensor accuracy changes.
+ }
+
+ CamRenderer mRenderer;
+ Camera mCamera;
+
+ SensorManager mSensorManager;
+ Sensor mAcceleration;
+}
+
+class CamRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
+
+ public CamRenderer(Context context) {
+ mContext = context;
+
+ mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length
+ * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mTriangleVertices.put(mTriangleVerticesData).position(0);
+
+ Matrix.setIdentityM(mSTMatrix, 0);
+ Matrix.setIdentityM(mMMatrix, 0);
+
+ float[] defaultAcceleration = {0.f,0.f,0.f};
+ setAcceleration(defaultAcceleration);
+ mPos[0] = 0.f;
+ mPos[1] = 0.f;
+ mPos[2] = 0.f;
+ mVel[0] = 0.f;
+ mVel[1] = 0.f;
+ mVel[2] = 0.f;
+
+ }
+
+ /* The following set methods are not synchronized, so should only
+ * be called within the rendering thread context. Use GLSurfaceView.queueEvent for safe access.
+ */
+ public void setPosition(float x, float y) {
+ /* Map from screen (0,0)-(1,1) to scene coordinates */
+ mPos[0] = (x*2-1)*mRatio;
+ mPos[1] = (-y)*2+1;
+ mPos[2] = 0.f;
+ mVel[0] = 0;
+ mVel[1] = 0;
+ mVel[2] = 0;
+ }
+
+ public void setCamera(Camera camera) {
+ mCamera = camera;
+ Camera.Size previewSize = camera.getParameters().getPreviewSize();
+ mCameraRatio = (float)previewSize.width/previewSize.height;
+ }
+
+ public void setAcceleration(float[] accelerationVector) {
+ mGForce[0] = accelerationVector[0];
+ mGForce[1] = accelerationVector[1];
+ mGForce[2] = accelerationVector[2];
+ }
+
+ public void onDrawFrame(GL10 glUnused) {
+ synchronized(this) {
+ if (updateSurface) {
+ mSurface.updateTexImage();
+
+ mSurface.getTransformMatrix(mSTMatrix);
+ long timestamp = mSurface.getTimestamp();
+ doPhysics(timestamp);
+
+ updateSurface = false;
+ }
+ }
+
+ // Ignore the passed-in GL10 interface, and use the GLES20
+ // class's static methods instead.
+ GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+ GLES20.glUseProgram(mProgram);
+ checkGlError("glUseProgram");
+
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
+ GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
+
+ mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
+ GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
+ TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+ checkGlError("glVertexAttribPointer maPosition");
+ GLES20.glEnableVertexAttribArray(maPositionHandle);
+ checkGlError("glEnableVertexAttribArray maPositionHandle");
+
+ mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
+ GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT, false,
+ TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+ checkGlError("glVertexAttribPointer maTextureHandle");
+ GLES20.glEnableVertexAttribArray(maTextureHandle);
+ checkGlError("glEnableVertexAttribArray maTextureHandle");
+
+ Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
+ Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
+
+ GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
+ GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
+ GLES20.glUniform1f(muCRatioHandle, mCameraRatio);
+
+ GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
+ checkGlError("glDrawArrays");
+ }
+
+ public void onSurfaceChanged(GL10 glUnused, int width, int height) {
+ // Ignore the passed-in GL10 interface, and use the GLES20
+ // class's static methods instead.
+ GLES20.glViewport(0, 0, width, height);
+ mRatio = (float) width / height;
+ Matrix.frustumM(mProjMatrix, 0, -mRatio, mRatio, -1, 1, 3, 7);
+ }
+
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
+ // Ignore the passed-in GL10 interface, and use the GLES20
+ // class's static methods instead.
+
+ /* Set up alpha blending and an Android background color */
+ GLES20.glEnable(GLES20.GL_BLEND);
+ GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
+ GLES20.glClearColor(0.643f, 0.776f, 0.223f, 1.0f);
+
+ /* Set up shaders and handles to their variables */
+ mProgram = createProgram(mVertexShader, mFragmentShader);
+ if (mProgram == 0) {
+ return;
+ }
+ maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
+ checkGlError("glGetAttribLocation aPosition");
+ if (maPositionHandle == -1) {
+ throw new RuntimeException("Could not get attrib location for aPosition");
+ }
+ maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
+ checkGlError("glGetAttribLocation aTextureCoord");
+ if (maTextureHandle == -1) {
+ throw new RuntimeException("Could not get attrib location for aTextureCoord");
+ }
+
+ muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
+ checkGlError("glGetUniformLocation uMVPMatrix");
+ if (muMVPMatrixHandle == -1) {
+ throw new RuntimeException("Could not get attrib location for uMVPMatrix");
+ }
+
+ muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix");
+ checkGlError("glGetUniformLocation uSTMatrix");
+ if (muMVPMatrixHandle == -1) {
+ throw new RuntimeException("Could not get attrib location for uSTMatrix");
+ }
+
+ muCRatioHandle = GLES20.glGetUniformLocation(mProgram, "uCRatio");
+ checkGlError("glGetUniformLocation uCRatio");
+ if (muMVPMatrixHandle == -1) {
+ throw new RuntimeException("Could not get attrib location for uCRatio");
+ }
+
+ /*
+ * Create our texture. This has to be done each time the
+ * surface is created.
+ */
+
+ int[] textures = new int[1];
+ GLES20.glGenTextures(1, textures, 0);
+
+ mTextureID = textures[0];
+ GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
+ checkGlError("glBindTexture mTextureID");
+
+ // Can't do mipmapping with camera source
+ GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
+ GLES20.GL_NEAREST);
+ GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
+ GLES20.GL_LINEAR);
+ // Clamp to edge is the only option
+ GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S,
+ GLES20.GL_CLAMP_TO_EDGE);
+ GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
+ GLES20.GL_CLAMP_TO_EDGE);
+ checkGlError("glTexParameteri mTextureID");
+
+ /*
+ * Create the SurfaceTexture that will feed this textureID, and pass it to the camera
+ */
+
+ mSurface = new SurfaceTexture(mTextureID);
+ mSurface.setOnFrameAvailableListener(this);
+ try {
+ mCamera.setPreviewTexture(mSurface);
+ } catch (IOException t) {
+ Log.e(TAG, "Cannot set preview texture target!");
+ }
+
+ /* Start the camera */
+ mCamera.startPreview();
+
+ Matrix.setLookAtM(mVMatrix, 0, 0, 0, 5f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
+
+ mLastTime = 0;
+
+ synchronized(this) {
+ updateSurface = false;
+ }
+ }
+
+ synchronized public void onFrameAvailable(SurfaceTexture surface) {
+ /* For simplicity, SurfaceTexture calls here when it has new
+ * data available. Call may come in from some random thread,
+ * so let's be safe and use synchronize. No OpenGL calls can be done here.
+ */
+ updateSurface = true;
+ }
+
+ private void doPhysics(long timestamp) {
+ /*
+ * Move the camera surface around based on some simple spring physics with drag
+ */
+
+ if (mLastTime == 0)
+ mLastTime = timestamp;
+
+ float deltaT = (timestamp - mLastTime)/1000000000.f; // To seconds
+
+ float springStrength = 20.f;
+ float frictionCoeff = 10.f;
+ float mass = 10.f;
+ float gMultiplier = 4.f;
+ /* Only update physics every 30 ms */
+ if (deltaT > 0.030f) {
+ mLastTime = timestamp;
+
+ float[] totalForce = new float[3];
+ totalForce[0] = -mPos[0] * springStrength - mVel[0]*frictionCoeff + gMultiplier*mGForce[0]*mass;
+ totalForce[1] = -mPos[1] * springStrength - mVel[1]*frictionCoeff + gMultiplier*mGForce[1]*mass;
+ totalForce[2] = -mPos[2] * springStrength - mVel[2]*frictionCoeff + gMultiplier*mGForce[2]*mass;
+
+ float[] accel = new float[3];
+ accel[0] = totalForce[0]/mass;
+ accel[1] = totalForce[1]/mass;
+ accel[2] = totalForce[2]/mass;
+
+ /* Not a very accurate integrator */
+ mVel[0] = mVel[0] + accel[0]*deltaT;
+ mVel[1] = mVel[1] + accel[1]*deltaT;
+ mVel[2] = mVel[2] + accel[2]*deltaT;
+
+ mPos[0] = mPos[0] + mVel[0]*deltaT;
+ mPos[1] = mPos[1] + mVel[1]*deltaT;
+ mPos[2] = mPos[2] + mVel[2]*deltaT;
+
+ Matrix.setIdentityM(mMMatrix, 0);
+ Matrix.translateM(mMMatrix, 0, mPos[0], mPos[1], mPos[2]);
+ }
+
+ }
+
+ private int loadShader(int shaderType, String source) {
+ int shader = GLES20.glCreateShader(shaderType);
+ if (shader != 0) {
+ GLES20.glShaderSource(shader, source);
+ GLES20.glCompileShader(shader);
+ int[] compiled = new int[1];
+ GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
+ if (compiled[0] == 0) {
+ Log.e(TAG, "Could not compile shader " + shaderType + ":");
+ Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
+ GLES20.glDeleteShader(shader);
+ shader = 0;
+ }
+ }
+ return shader;
+ }
+
+ private int createProgram(String vertexSource, String fragmentSource) {
+ int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
+ if (vertexShader == 0) {
+ return 0;
+ }
+ int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
+ if (pixelShader == 0) {
+ return 0;
+ }
+
+ int program = GLES20.glCreateProgram();
+ if (program != 0) {
+ GLES20.glAttachShader(program, vertexShader);
+ checkGlError("glAttachShader");
+ GLES20.glAttachShader(program, pixelShader);
+ checkGlError("glAttachShader");
+ GLES20.glLinkProgram(program);
+ int[] linkStatus = new int[1];
+ GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
+ if (linkStatus[0] != GLES20.GL_TRUE) {
+ Log.e(TAG, "Could not link program: ");
+ Log.e(TAG, GLES20.glGetProgramInfoLog(program));
+ GLES20.glDeleteProgram(program);
+ program = 0;
+ }
+ }
+ return program;
+ }
+
+ private void checkGlError(String op) {
+ int error;
+ while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
+ Log.e(TAG, op + ": glError " + error);
+ throw new RuntimeException(op + ": glError " + error);
+ }
+ }
+
+ private static final int FLOAT_SIZE_BYTES = 4;
+ private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+ private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
+ private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
+ private final float[] mTriangleVerticesData = {
+ // X, Y, Z, U, V
+ -1.0f, -1.0f, 0, 0.f, 0.f,
+ 1.0f, -1.0f, 0, 1.f, 0.f,
+ -1.0f, 1.0f, 0, 0.f, 1.f,
+ 1.0f, 1.0f, 0, 1.f, 1.f,
+ };
+
+ private FloatBuffer mTriangleVertices;
+
+ private final String mVertexShader =
+ "uniform mat4 uMVPMatrix;\n" +
+ "uniform mat4 uSTMatrix;\n" +
+ "uniform float uCRatio;\n" +
+ "attribute vec4 aPosition;\n" +
+ "attribute vec4 aTextureCoord;\n" +
+ "varying vec2 vTextureCoord;\n" +
+ "varying vec2 vTextureNormCoord;\n" +
+ "void main() {\n" +
+ " vec4 scaledPos = aPosition;\n" +
+ " scaledPos.x = scaledPos.x * uCRatio;\n" +
+ " gl_Position = uMVPMatrix * scaledPos;\n" +
+ " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
+ " vTextureNormCoord = aTextureCoord.xy;\n" +
+ "}\n";
+
+ private final String mFragmentShader =
+ "#extension GL_OES_EGL_image_external : require\n" +
+ "precision mediump float;\n" +
+ "varying vec2 vTextureCoord;\n" +
+ "varying vec2 vTextureNormCoord;\n" +
+ "uniform samplerExternalOES sTexture;\n" +
+ "void main() {\n" +
+ " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
+ " gl_FragColor.a = 1.0-min(length(vTextureNormCoord-0.5)*2.0,1.0);\n" +
+ "}\n";
+
+ private float[] mMVPMatrix = new float[16];
+ private float[] mProjMatrix = new float[16];
+ private float[] mMMatrix = new float[16];
+ private float[] mVMatrix = new float[16];
+ private float[] mSTMatrix = new float[16];
+
+ private int mProgram;
+ private int mTextureID;
+ private int muMVPMatrixHandle;
+ private int muSTMatrixHandle;
+ private int muCRatioHandle;
+ private int maPositionHandle;
+ private int maTextureHandle;
+
+ private float mRatio = 1.0f;
+ private float mCameraRatio = 1.0f;
+ private float[] mVel = new float[3];
+ private float[] mPos = new float[3];
+ private float[] mGForce = new float[3];
+
+ private long mLastTime;
+
+ private SurfaceTexture mSurface;
+ private Camera mCamera;
+ private boolean updateSurface = false;
+
+ private Context mContext;
+ private static String TAG = "CamRenderer";
+
+ // Magic key
+ private static int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
+}
diff --git a/opengl/tools/glgen/specs/gles11/checks.spec b/opengl/tools/glgen/specs/gles11/checks.spec
index f917128..f478a32 100644
--- a/opengl/tools/glgen/specs/gles11/checks.spec
+++ b/opengl/tools/glgen/specs/gles11/checks.spec
@@ -31,28 +31,12 @@ glDrawTexfvOES check coords 5
glDrawTexivOES check coords 5
glDrawTexsvOES check coords 5
glDrawTexxvOES check coords 5
-glBindFramebufferOES unsupported
-glBindRenderbufferOES unsupported
-glBlendEquation unsupported
-glBlendEquationSeparate unsupported
-glBlendFuncSeparate unsupported
-glCheckFramebufferStatusOES unsupported return 0
-glDeleteFramebuffersOES unsupported
-glDeleteRenderbuffersOES unsupported
-glFramebufferRenderbufferOES unsupported
-glFramebufferStorageOES unsupported
-glFramebufferTexture2DOES unsupported
-glGenFramebuffersOES unsupported
-glGenRenderbuffersOES unsupported
-glGenerateMipmapOES unsupported
-glGetBufferParameter unsupported
-glGetFramebufferAttachmentParameterivOES unsupported
-glGetRenderbufferParameterivOES unsupported
-glGetTexGen unsupported
-glIsFramebufferOES unsupported return JNI_FALSE
-glIsRenderbufferOES unsupported return JNI_FALSE
-glRenderbufferStorageOES unsupported return false
-glTexGen unsupported
-glTexGenf unsupported
-glTexGeni unsupported
-glTexGenx unsupported
+glDeleteFramebuffersOES check framebuffers n
+glDeleteRenderbuffersOES check renderbuffers n
+glGenFramebuffersOES check framebuffers n
+glGenRenderbuffersOES check renderbuffers n
+glGetBufferParameter check params 1
+glGetFramebufferAttachmentParameterivOES check params 1
+glGetRenderbufferParameterivOES check params 1
+glGetTexGen ifcheck params 1 pname GL_TEXTURE_GEN_MODE ifcheck params 4 pname GL_OBJECT_PLANE,GL_EYE_PLANE
+
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 8e18f2a..4fa5bcb 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -646,12 +646,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* Create (if necessary) and launch the recent apps dialog
*/
void showRecentAppsDialog() {
- if (mRecentAppsDialog == null) {
- mRecentAppsDialog = new RecentApplicationsDialog(mContext);
- }
- mRecentAppsDialog.show();
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mRecentAppsDialog == null) {
+ mRecentAppsDialog = new RecentApplicationsDialog(mContext);
+ }
+ mRecentAppsDialog.show();
+ }
+ });
}
-
+
/** {@inheritDoc} */
public void init(Context context, IWindowManager windowManager,
LocalPowerManager powerManager) {
@@ -1386,7 +1391,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
return false;
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
- if (!down) {
+ if (down && repeatCount == 0) {
showRecentAppsDialog();
}
return true;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a09e16b..f3c9959 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -666,20 +666,6 @@ void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
mHardware->releaseRecordingFrame(mem);
}
-int32_t CameraService::Client::getNumberOfVideoBuffers() const {
- LOG1("getNumberOfVideoBuffers");
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return 0;
- return mHardware->getNumberOfVideoBuffers();
-}
-
-sp<IMemory> CameraService::Client::getVideoBuffer(int32_t index) const {
- LOG1("getVideoBuffer: %d", index);
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return 0;
- return mHardware->getVideoBuffer(index);
-}
-
status_t CameraService::Client::storeMetaDataInBuffers(bool enabled)
{
LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
@@ -938,7 +924,7 @@ void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
switch (msgType) {
case CAMERA_MSG_SHUTTER:
// ext1 is the dimension of the yuv picture.
- client->handleShutter((image_rect_type *)ext1);
+ client->handleShutter();
break;
default:
client->handleGenericNotify(msgType, ext1, ext2);
@@ -997,9 +983,7 @@ void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
}
// snapshot taken callback
-// "size" is the width and height of yuv picture for registerBuffer.
-// If it is NULL, use the picture size from parameters.
-void CameraService::Client::handleShutter(image_rect_type *size) {
+void CameraService::Client::handleShutter(void) {
if (mPlayShutterSound) {
mCameraService->playSound(SOUND_SHUTTER);
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 1c43b00..28e8cc0 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -99,8 +99,6 @@ private:
virtual status_t startPreview();
virtual void stopPreview();
virtual bool previewEnabled();
- virtual int32_t getNumberOfVideoBuffers() const;
- virtual sp<IMemory> getVideoBuffer(int32_t index) const;
virtual status_t storeMetaDataInBuffers(bool enabled);
virtual status_t startRecording();
virtual void stopRecording();
@@ -152,7 +150,7 @@ private:
// convert client from cookie
static sp<Client> getClientFromCookie(void* user);
// handlers for messages
- void handleShutter(image_rect_type *size);
+ void handleShutter(void);
void handlePreviewData(const sp<IMemory>& mem);
void handlePostview(const sp<IMemory>& mem);
void handleRawPicture(const sp<IMemory>& mem);
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index feca58d..6ea068a 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -563,18 +563,19 @@ void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropR
}
switch (entry->type) {
- case EventEntry::TYPE_KEY:
- synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CANCEL_NON_POINTER_EVENTS, reason);
+ case EventEntry::TYPE_KEY: {
+ CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
+ synthesizeCancelationEventsForAllConnectionsLocked(options);
break;
+ }
case EventEntry::TYPE_MOTION: {
MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
- synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CANCEL_POINTER_EVENTS, reason);
+ CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, reason);
+ synthesizeCancelationEventsForAllConnectionsLocked(options);
} else {
- synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CANCEL_NON_POINTER_EVENTS, reason);
+ CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
+ synthesizeCancelationEventsForAllConnectionsLocked(options);
}
break;
}
@@ -903,8 +904,9 @@ bool InputDispatcher::dispatchMotionLocked(
// Dispatch the motion.
if (conflictingPointerActions) {
- synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CANCEL_POINTER_EVENTS, "Conflicting pointer actions.");
+ CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+ "conflicting pointer actions");
+ synthesizeCancelationEventsForAllConnectionsLocked(options);
}
dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
return true;
@@ -1070,9 +1072,9 @@ void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
if (connection->status == Connection::STATUS_NORMAL) {
- synthesizeCancelationEventsForConnectionLocked(
- connection, InputState::CANCEL_ALL_EVENTS,
+ CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
"application not responding");
+ synthesizeCancelationEventsForConnectionLocked(connection, options);
}
}
}
@@ -2169,26 +2171,24 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data
}
void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CancelationOptions options, const char* reason) {
+ const CancelationOptions& options) {
for (size_t i = 0; i < mConnectionsByReceiveFd.size(); i++) {
synthesizeCancelationEventsForConnectionLocked(
- mConnectionsByReceiveFd.valueAt(i), options, reason);
+ mConnectionsByReceiveFd.valueAt(i), options);
}
}
void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
- const sp<InputChannel>& channel, InputState::CancelationOptions options,
- const char* reason) {
+ const sp<InputChannel>& channel, const CancelationOptions& options) {
ssize_t index = getConnectionIndexLocked(channel);
if (index >= 0) {
synthesizeCancelationEventsForConnectionLocked(
- mConnectionsByReceiveFd.valueAt(index), options, reason);
+ mConnectionsByReceiveFd.valueAt(index), options);
}
}
void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
- const sp<Connection>& connection, InputState::CancelationOptions options,
- const char* reason) {
+ const sp<Connection>& connection, const CancelationOptions& options) {
nsecs_t currentTime = now();
mTempCancelationEvents.clear();
@@ -2199,8 +2199,9 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
&& connection->status != Connection::STATUS_BROKEN) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
LOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
- "with reality: %s, options=%d.",
- connection->getInputChannelName(), mTempCancelationEvents.size(), reason, options);
+ "with reality: %s, mode=%d.",
+ connection->getInputChannelName(), mTempCancelationEvents.size(),
+ options.reason, options.mode);
#endif
for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
@@ -2870,8 +2871,9 @@ void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
LOGD("Focus left window: %s",
oldFocusedWindowChannel->getName().string());
#endif
- synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel,
- InputState::CANCEL_NON_POINTER_EVENTS, "focus left window");
+ CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
+ "focus left window");
+ synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel, options);
oldFocusedWindowChannel.clear();
}
}
@@ -2892,8 +2894,9 @@ void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
#if DEBUG_FOCUS
LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
#endif
- synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel,
- InputState::CANCEL_POINTER_EVENTS, "touched window was removed");
+ CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+ "touched window was removed");
+ synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel, options);
mTouchState.windows.removeAt(i);
}
}
@@ -3036,9 +3039,9 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
sp<Connection> toConnection = mConnectionsByReceiveFd.valueAt(toConnectionIndex);
fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
- synthesizeCancelationEventsForConnectionLocked(fromConnection,
- InputState::CANCEL_POINTER_EVENTS,
+ CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
"transferring touch focus from this window to another window");
+ synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
}
#if DEBUG_FOCUS
@@ -3056,7 +3059,8 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
LOGD("Resetting and dropping all events (%s).", reason);
#endif
- synthesizeCancelationEventsForAllConnectionsLocked(InputState::CANCEL_ALL_EVENTS, reason);
+ CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, reason);
+ synthesizeCancelationEventsForAllConnectionsLocked(options);
resetKeyRepeatLocked();
releasePendingEventLocked();
@@ -3386,58 +3390,49 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
if (!connection->outboundQueue.isEmpty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
if (dispatchEntry->inProgress
- && dispatchEntry->hasForegroundTarget()
&& dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
- if (handled) {
- // If the application handled a non-fallback key, then immediately
- // cancel all fallback keys previously dispatched to the application.
- // This behavior will prevent chording with fallback keys (so they cannot
- // be used as modifiers) but it will ensure that fallback keys do not
- // get stuck. This takes care of the case where the application does not handle
- // the original DOWN so we generate a fallback DOWN but it does handle
- // the original UP in which case we want to send a fallback CANCEL.
- synthesizeCancelationEventsForConnectionLocked(connection,
- InputState::CANCEL_FALLBACK_EVENTS,
- "application handled a non-fallback event, "
- "canceling all fallback events");
- connection->originalKeyCodeForFallback = -1;
+ // Get the fallback key state.
+ // Clear it out after dispatching the UP.
+ int32_t originalKeyCode = keyEntry->keyCode;
+ int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
+ if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
+ connection->inputState.removeFallbackKey(originalKeyCode);
+ }
+
+ if (handled || !dispatchEntry->hasForegroundTarget()) {
+ // If the application handles the original key for which we previously
+ // generated a fallback or if the window is not a foreground window,
+ // then cancel the associated fallback key, if any.
+ if (fallbackKeyCode != -1) {
+ if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
+ CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
+ "application handled the original non-fallback key "
+ "or is no longer a foreground target, "
+ "canceling previously dispatched fallback key");
+ options.keyCode = fallbackKeyCode;
+ synthesizeCancelationEventsForConnectionLocked(connection, options);
+ }
+ connection->inputState.removeFallbackKey(originalKeyCode);
+ }
} else {
// If the application did not handle a non-fallback key, first check
- // that we are in a good state to handle the fallback key. Then ask
- // the policy what to do with it.
- if (connection->originalKeyCodeForFallback < 0) {
- if (keyEntry->action != AKEY_EVENT_ACTION_DOWN
- || keyEntry->repeatCount != 0) {
+ // that we are in a good state to perform unhandled key event processing
+ // Then ask the policy what to do with it.
+ bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN
+ && keyEntry->repeatCount == 0;
+ if (fallbackKeyCode == -1 && !initialDown) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("Unhandled key event: Skipping fallback since this "
- "is not an initial down. "
- "keyCode=%d, action=%d, repeatCount=%d",
- keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount);
+ LOGD("Unhandled key event: Skipping unhandled key event processing "
+ "since this is not an initial down. "
+ "keyCode=%d, action=%d, repeatCount=%d",
+ originalKeyCode, keyEntry->action, keyEntry->repeatCount);
#endif
- goto SkipFallback;
- }
-
- // Start handling the fallback key on DOWN.
- connection->originalKeyCodeForFallback = keyEntry->keyCode;
- } else {
- if (keyEntry->keyCode != connection->originalKeyCodeForFallback) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("Unhandled key event: Skipping fallback since there is "
- "already a different fallback in progress. "
- "keyCode=%d, originalKeyCodeForFallback=%d",
- keyEntry->keyCode, connection->originalKeyCodeForFallback);
-#endif
- goto SkipFallback;
- }
-
- // Finish handling the fallback key on UP.
- if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
- connection->originalKeyCodeForFallback = -1;
- }
+ goto SkipFallback;
}
+ // Dispatch the unhandled key to the policy.
#if DEBUG_OUTBOUND_EVENT_DETAILS
LOGD("Unhandled key event: Asking policy to perform fallback action. "
"keyCode=%d, action=%d, repeatCount=%d",
@@ -3454,18 +3449,78 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
mLock.lock();
if (connection->status != Connection::STATUS_NORMAL) {
+ connection->inputState.removeFallbackKey(originalKeyCode);
return;
}
assert(connection->outboundQueue.headSentinel.next == dispatchEntry);
+ // Latch the fallback keycode for this key on an initial down.
+ // The fallback keycode cannot change at any other point in the lifecycle.
+ if (initialDown) {
+ if (fallback) {
+ fallbackKeyCode = event.getKeyCode();
+ } else {
+ fallbackKeyCode = AKEYCODE_UNKNOWN;
+ }
+ connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
+ }
+
+ assert(fallbackKeyCode != -1);
+
+ // Cancel the fallback key if the policy decides not to send it anymore.
+ // We will continue to dispatch the key to the policy but we will no
+ // longer dispatch a fallback key to the application.
+ if (fallbackKeyCode != AKEYCODE_UNKNOWN
+ && (!fallback || fallbackKeyCode != event.getKeyCode())) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ if (fallback) {
+ LOGD("Unhandled key event: Policy requested to send key %d"
+ "as a fallback for %d, but on the DOWN it had requested "
+ "to send %d instead. Fallback canceled.",
+ event.getKeyCode(), originalKeyCode, fallbackKeyCode);
+ } else {
+ LOGD("Unhandled key event: Policy did not request fallback for %d,"
+ "but on the DOWN it had requested to send %d. "
+ "Fallback canceled.",
+ originalKeyCode, fallbackKeyCode);
+ }
+#endif
+
+ CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
+ "canceling fallback, policy no longer desires it");
+ options.keyCode = fallbackKeyCode;
+ synthesizeCancelationEventsForConnectionLocked(connection, options);
+
+ fallback = false;
+ fallbackKeyCode = AKEYCODE_UNKNOWN;
+ if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
+ connection->inputState.setFallbackKey(originalKeyCode,
+ fallbackKeyCode);
+ }
+ }
+
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ {
+ String8 msg;
+ const KeyedVector<int32_t, int32_t>& fallbackKeys =
+ connection->inputState.getFallbackKeys();
+ for (size_t i = 0; i < fallbackKeys.size(); i++) {
+ msg.appendFormat(", %d->%d", fallbackKeys.keyAt(i),
+ fallbackKeys.valueAt(i));
+ }
+ LOGD("Unhandled key event: %d currently tracked fallback keys%s.",
+ fallbackKeys.size(), msg.string());
+ }
+#endif
+
if (fallback) {
// Restart the dispatch cycle using the fallback key.
keyEntry->eventTime = event.getEventTime();
keyEntry->deviceId = event.getDeviceId();
keyEntry->source = event.getSource();
keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
- keyEntry->keyCode = event.getKeyCode();
+ keyEntry->keyCode = fallbackKeyCode;
keyEntry->scanCode = event.getScanCode();
keyEntry->metaState = event.getMetaState();
keyEntry->repeatCount = event.getRepeatCount();
@@ -3474,13 +3529,17 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
#if DEBUG_OUTBOUND_EVENT_DETAILS
LOGD("Unhandled key event: Dispatching fallback key. "
- "fallbackKeyCode=%d, fallbackMetaState=%08x",
- keyEntry->keyCode, keyEntry->metaState);
+ "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
+ originalKeyCode, fallbackKeyCode, keyEntry->metaState);
#endif
dispatchEntry->inProgress = false;
startDispatchCycleLocked(now(), connection);
return;
+ } else {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ LOGD("Unhandled key event: No fallback key.");
+#endif
}
}
}
@@ -3774,6 +3833,17 @@ void InputDispatcher::InputState::trackEvent(const EventEntry* entry, int32_t ac
}
void InputDispatcher::InputState::trackKey(const KeyEntry* entry, int32_t action) {
+ if (action == AKEY_EVENT_ACTION_UP
+ && (entry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
+ for (size_t i = 0; i < mFallbackKeys.size(); ) {
+ if (mFallbackKeys.valueAt(i) == entry->keyCode) {
+ mFallbackKeys.removeItemsAt(i);
+ } else {
+ i += 1;
+ }
+ }
+ }
+
for (size_t i = 0; i < mKeyMementos.size(); i++) {
KeyMemento& memento = mKeyMementos.editItemAt(i);
if (memento.deviceId == entry->deviceId
@@ -3867,7 +3937,7 @@ void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry*
void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
Allocator* allocator, Vector<EventEntry*>& outEvents,
- CancelationOptions options) {
+ const CancelationOptions& options) {
for (size_t i = 0; i < mKeyMementos.size(); ) {
const KeyMemento& memento = mKeyMementos.itemAt(i);
if (shouldCancelKey(memento, options)) {
@@ -3902,6 +3972,7 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim
void InputDispatcher::InputState::clear() {
mKeyMementos.clear();
mMotionMementos.clear();
+ mFallbackKeys.clear();
}
void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
@@ -3922,13 +3993,36 @@ void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
}
}
+int32_t InputDispatcher::InputState::getFallbackKey(int32_t originalKeyCode) {
+ ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
+ return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
+}
+
+void InputDispatcher::InputState::setFallbackKey(int32_t originalKeyCode,
+ int32_t fallbackKeyCode) {
+ ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
+ if (index >= 0) {
+ mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
+ } else {
+ mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
+ }
+}
+
+void InputDispatcher::InputState::removeFallbackKey(int32_t originalKeyCode) {
+ mFallbackKeys.removeItem(originalKeyCode);
+}
+
bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
- CancelationOptions options) {
- switch (options) {
- case CANCEL_ALL_EVENTS:
- case CANCEL_NON_POINTER_EVENTS:
+ const CancelationOptions& options) {
+ if (options.keyCode != -1 && memento.keyCode != options.keyCode) {
+ return false;
+ }
+
+ switch (options.mode) {
+ case CancelationOptions::CANCEL_ALL_EVENTS:
+ case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
return true;
- case CANCEL_FALLBACK_EVENTS:
+ case CancelationOptions::CANCEL_FALLBACK_EVENTS:
return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
default:
return false;
@@ -3936,13 +4030,13 @@ bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
}
bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
- CancelationOptions options) {
- switch (options) {
- case CANCEL_ALL_EVENTS:
+ const CancelationOptions& options) {
+ switch (options.mode) {
+ case CancelationOptions::CANCEL_ALL_EVENTS:
return true;
- case CANCEL_POINTER_EVENTS:
+ case CancelationOptions::CANCEL_POINTER_EVENTS:
return memento.source & AINPUT_SOURCE_CLASS_POINTER;
- case CANCEL_NON_POINTER_EVENTS:
+ case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
default:
return false;
@@ -3956,8 +4050,7 @@ InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle) :
status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
inputPublisher(inputChannel),
- lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
- originalKeyCodeForFallback(-1) {
+ lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
}
InputDispatcher::Connection::~Connection() {
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 59c5298..48e4d43 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -610,18 +610,32 @@ private:
void releaseEventEntryInjectionState(EventEntry* entry);
};
- /* Tracks dispatched key and motion event state so that cancelation events can be
- * synthesized when events are dropped. */
- class InputState {
- public:
- // Specifies the sources to cancel.
- enum CancelationOptions {
+ /* Specifies which events are to be canceled and why. */
+ struct CancelationOptions {
+ enum Mode {
CANCEL_ALL_EVENTS = 0,
CANCEL_POINTER_EVENTS = 1,
CANCEL_NON_POINTER_EVENTS = 2,
CANCEL_FALLBACK_EVENTS = 3,
};
+ // The criterion to use to determine which events should be canceled.
+ Mode mode;
+
+ // Descriptive reason for the cancelation.
+ const char* reason;
+
+ // The specific keycode of the key event to cancel, or -1 to cancel any key event.
+ int32_t keyCode;
+
+ CancelationOptions(Mode mode, const char* reason) :
+ mode(mode), reason(reason), keyCode(-1) { }
+ };
+
+ /* Tracks dispatched key and motion event state so that cancelation events can be
+ * synthesized when events are dropped. */
+ class InputState {
+ public:
InputState();
~InputState();
@@ -639,7 +653,7 @@ private:
// Synthesizes cancelation events for the current state and resets the tracked state.
void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator,
- Vector<EventEntry*>& outEvents, CancelationOptions options);
+ Vector<EventEntry*>& outEvents, const CancelationOptions& options);
// Clears the current state.
void clear();
@@ -647,6 +661,21 @@ private:
// Copies pointer-related parts of the input state to another instance.
void copyPointerStateTo(InputState& other) const;
+ // Gets the fallback key associated with a keycode.
+ // Returns -1 if none.
+ // Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy.
+ int32_t getFallbackKey(int32_t originalKeyCode);
+
+ // Sets the fallback key for a particular keycode.
+ void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode);
+
+ // Removes the fallback key for a particular keycode.
+ void removeFallbackKey(int32_t originalKeyCode);
+
+ inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const {
+ return mFallbackKeys;
+ }
+
private:
struct KeyMemento {
int32_t deviceId;
@@ -673,11 +702,12 @@ private:
Vector<KeyMemento> mKeyMementos;
Vector<MotionMemento> mMotionMementos;
+ KeyedVector<int32_t, int32_t> mFallbackKeys;
static bool shouldCancelKey(const KeyMemento& memento,
- CancelationOptions options);
+ const CancelationOptions& options);
static bool shouldCancelMotion(const MotionMemento& memento,
- CancelationOptions options);
+ const CancelationOptions& options);
};
/* Manages the dispatch state associated with a single input channel. */
@@ -704,7 +734,6 @@ private:
nsecs_t lastEventTime; // the time when the event was originally captured
nsecs_t lastDispatchTime; // the time when the last event was dispatched
- int32_t originalKeyCodeForFallback; // original keycode for fallback in progress, -1 if none
explicit Connection(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle);
@@ -953,11 +982,11 @@ private:
static int handleReceiveCallback(int receiveFd, int events, void* data);
void synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CancelationOptions options, const char* reason);
+ const CancelationOptions& options);
void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
- InputState::CancelationOptions options, const char* reason);
+ const CancelationOptions& options);
void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
- InputState::CancelationOptions options, const char* reason);
+ const CancelationOptions& options);
// Splitting motion events across windows.
MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index c022123..96cf4bd 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -789,7 +789,9 @@ bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& input
jobject fallbackKeyEventObj = env->CallObjectMethod(mCallbacksObj,
gCallbacksClassInfo.dispatchUnhandledKey,
inputWindowHandleObj, keyEventObj, policyFlags);
- checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey");
+ if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) {
+ fallbackKeyEventObj = NULL;
+ }
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
@@ -820,7 +822,9 @@ bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
JNIEnv* env = jniEnv();
jboolean result = env->CallBooleanMethod(mCallbacksObj,
gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
- checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
+ if (checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission")) {
+ result = false;
+ }
return result;
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index d4a3c0a..8a029f1 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -42,6 +42,7 @@ import com.android.internal.R;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -244,9 +245,29 @@ public abstract class DataConnectionTracker extends Handler {
protected HashMap<Integer, DataConnection> mDataConnections =
new HashMap<Integer, DataConnection>();
+ /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
+ protected HashMap<String, Integer> mApnToDataConnectionId =
+ new HashMap<String, Integer>();
+
+ /** Phone.APN_TYPE_* ===> ApnContext */
+ protected ConcurrentHashMap<String, ApnContext> mApnContexts;
+
/* Currently active APN */
protected ApnSetting mActiveApn;
+ /** allApns holds all apns */
+ protected ArrayList<ApnSetting> mAllApns = null;
+
+ /** preferred apn */
+ protected ApnSetting mPreferredApn = null;
+
+ /** Is packet service restricted by network */
+ protected boolean mIsPsRestricted = false;
+
+
+ /* Once disposed dont handle any messages */
+ protected boolean mIsDisposed = false;
+
protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
{
@Override
@@ -327,6 +348,7 @@ public abstract class DataConnectionTracker extends Handler {
}
public void dispose() {
+ mIsDisposed = true;
mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
}
@@ -340,11 +362,6 @@ public abstract class DataConnectionTracker extends Handler {
return mActivity;
}
- public State getState() {
- // TODO: reimplement to use apnType better yet REMOVE.
- return mState;
- }
-
/**
* @return the data connections
*/
@@ -386,16 +403,7 @@ public abstract class DataConnectionTracker extends Handler {
return result;
}
- private String getActiveApnType() {
- String result;
- if (mActiveApn != null) {
- result = apnIdToType(mActiveApn.id);
- } else {
- result = null;
- }
- return result;
- }
-
+ /** TODO: See if we can remove */
public String getActiveApnString() {
String result = null;
if (mActiveApn != null) {
@@ -430,10 +438,19 @@ public abstract class DataConnectionTracker extends Handler {
}
}
-
+ // abstract methods
protected abstract String getActionIntentReconnectAlarm();
+ protected abstract void startNetStatPoll();
+ protected abstract void stopNetStatPoll();
+ protected abstract void restartRadio();
+ protected abstract void log(String s);
+ protected abstract void loge(String s);
+ protected abstract boolean isDataAllowed();
+ protected abstract boolean isApnTypeAvailable(String type);
+ public abstract State getState(String apnType);
+ protected abstract void setState(State s);
+ protected abstract void gotoIdleAndNotifyDataConnection(String reason);
- // abstract handler methods
protected abstract boolean onTrySetupData(String reason);
protected abstract void onRoamingOff();
protected abstract void onRoamingOn();
@@ -542,16 +559,6 @@ public abstract class DataConnectionTracker extends Handler {
return result;
}
- protected abstract void startNetStatPoll();
-
- protected abstract void stopNetStatPoll();
-
- protected abstract void restartRadio();
-
- protected abstract void log(String s);
-
- protected abstract void loge(String s);
-
protected int apnTypeToId(String type) {
if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
return APN_DEFAULT_ID;
@@ -598,12 +605,6 @@ public abstract class DataConnectionTracker extends Handler {
}
}
- protected abstract boolean isApnTypeAvailable(String type);
-
- protected abstract void setState(State s);
-
- protected abstract void gotoIdleAndNotifyDataConnection(String reason);
-
protected LinkProperties getLinkProperties(String apnType) {
int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) {
@@ -724,13 +725,12 @@ public abstract class DataConnectionTracker extends Handler {
return possible;
}
- protected abstract boolean isDataAllowed();
-
public boolean isApnTypeEnabled(String apnType) {
if (apnType == null) {
- apnType = getActiveApnType();
+ return false;
+ } else {
+ return isApnIdEnabled(apnTypeToId(apnType));
}
- return isApnIdEnabled(apnTypeToId(apnType));
}
protected synchronized boolean isApnIdEnabled(int id) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
index 89d7174..8fd6de1 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -122,13 +122,7 @@ public class CDMALTEPhone extends CDMAPhone {
} else if (mDataConnection.isApnTypeEnabled(apnType) == false) {
ret = DataState.DISCONNECTED;
} else {
- DataConnectionTracker.State state;
- if (isCdmaDataConnectionTracker) {
- state = mDataConnection.getState();
- } else {
- state = ((GsmDataConnectionTracker)mDataConnection).getState(apnType);
- }
- switch (state) {
+ switch (mDataConnection.getState(apnType)) {
case FAILED:
case IDLE:
ret = DataState.DISCONNECTED;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index dd5091c..31abe34 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -633,7 +633,7 @@ public class CDMAPhone extends PhoneBase {
mDataConnection.isApnTypeActive(apnType) == false) {
ret = DataState.DISCONNECTED;
} else {
- switch (mDataConnection.getState()) {
+ switch (mDataConnection.getState(apnType)) {
case FAILED:
case IDLE:
ret = DataState.DISCONNECTED;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index b244945..01519a7 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -118,6 +118,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
@Override
public void dispose() {
+ cleanUpConnection(false, null);
+
super.dispose();
// Unregister from all events
@@ -158,6 +160,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
@Override
+ public synchronized State getState(String apnType) {
+ return mState;
+ }
+
+ @Override
protected boolean isApnTypeAvailable(String type) {
for (String s : mSupportedApnTypes) {
if (TextUtils.equals(type, s)) {
@@ -861,7 +868,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
@Override
public void handleMessage (Message msg) {
- if (!mPhone.mIsTheCurrentActivePhone) {
+ if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
log("Ignore CDMA msgs since CDMA phone is inactive");
return;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index 261a61a..36094a1 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -312,7 +312,7 @@ public class GSMPhone extends PhoneBase {
mDataConnection.isApnTypeActive(apnType) == false) {
ret = DataState.DISCONNECTED;
} else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */
- switch (mDataConnection.getState()) {
+ switch (mDataConnection.getState(apnType)) {
case FAILED:
case IDLE:
ret = DataState.DISCONNECTED;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 48e8ea9..22c4640 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -102,26 +102,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
//useful for debugging
boolean mFailNextConnect = false;
- /**
- * allApns holds all apns for this sim spn, retrieved from
- * the Carrier DB.
- *
- * Create once after simcard info is loaded
- */
- private ArrayList<ApnSetting> mAllApns = null;
-
- private ApnSetting mPreferredApn = null;
-
- /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
- private HashMap<String, Integer> mApnToDataConnectionId =
- new HashMap<String, Integer>();
-
- /** Phone.APN_TYPE_* ===> ApnContext */
- private ConcurrentHashMap<String, ApnContext> mApnContexts;
-
- /** Is packet service restricted by network */
- private boolean mIsPsRestricted = false;
-
//***** Constants
private static final int POLL_PDP_MILLIS = 5 * 1000;
@@ -192,6 +172,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
public void dispose() {
+ cleanUpAllConnections(false, null);
+
super.dispose();
//Unregister for all events
@@ -318,7 +300,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return null;
}
+ @Override
+ protected void setState(State s) {
+ if (DBG) log("setState should not be used in GSM" + s);
+ }
+
// Return state of specific apn type
+ @Override
public synchronized State getState(String apnType) {
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext != null) {
@@ -611,11 +599,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
- @Override
- protected void setState(State s) {
- if (DBG) log("setState should not be used in GSM" + s);
- }
-
private boolean trySetupData(ApnContext apnContext) {
if (DBG)
@@ -1791,7 +1774,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
public void handleMessage (Message msg) {
if (DBG) log("GSMDataConnTrack handleMessage "+msg);
- if (!mPhone.mIsTheCurrentActivePhone) {
+ if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
log("Ignore GSM msgs since GSM phone is inactive");
return;
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 7373cbb..5471289 100755..100644
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -40,6 +40,7 @@ import com.android.internal.telephony.PhoneNotifier;
import java.text.ParseException;
import java.util.List;
+import java.util.regex.Pattern;
/**
* {@hide}
@@ -386,8 +387,8 @@ public class SipPhone extends SipPhoneBase {
Connection dial(String originalNumber) throws SipException {
String calleeSipUri = originalNumber;
if (!calleeSipUri.contains("@")) {
- calleeSipUri = mProfile.getUriString().replaceFirst(
- mProfile.getUserName() + "@",
+ String replaceStr = Pattern.quote(mProfile.getUserName() + "@");
+ calleeSipUri = mProfile.getUriString().replaceFirst(replaceStr,
calleeSipUri + "@");
}
try {
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index ac580e7..4ee86b6 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -27,6 +27,8 @@ import java.text.ParseException;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
+import java.util.regex.Pattern;
+
import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.DialogTerminatedEvent;
@@ -215,9 +217,11 @@ class SipHelper {
String tag) throws ParseException, SipException {
FromHeader fromHeader = createFromHeader(userProfile, tag);
ToHeader toHeader = createToHeader(userProfile);
+
+ String replaceStr = Pattern.quote(userProfile.getUserName() + "@");
SipURI requestURI = mAddressFactory.createSipURI(
- userProfile.getUriString().replaceFirst(
- userProfile.getUserName() + "@", ""));
+ userProfile.getUriString().replaceFirst(replaceStr, ""));
+
List<ViaHeader> viaHeaders = createViaHeaders();
CallIdHeader callIdHeader = createCallIdHeader();
CSeqHeader cSeqHeader = createCSeqHeader(requestType);