Merge "Check for null ActivityInfo."
diff --git a/api/current.txt b/api/current.txt
index 37b0328..574af6b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2349,6 +2349,15 @@
method public void setPropertyName(java.lang.String);
}
+ public class TimeAnimator extends android.animation.ValueAnimator {
+ ctor public TimeAnimator();
+ method public void setTimeListener(android.animation.TimeAnimator.TimeListener);
+ }
+
+ public static abstract interface TimeAnimator.TimeListener {
+ method public abstract void onTimeUpdate(android.animation.TimeAnimator, long, long);
+ }
+
public abstract interface TimeInterpolator {
method public abstract float getInterpolation(float);
}
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 7a599e9..bee5880 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -28,6 +28,7 @@
#include <SkImageEncoder.h>
#include <SkBitmap.h>
+#include <SkData.h>
#include <SkStream.h>
using namespace android;
@@ -168,7 +169,9 @@
SkDynamicMemoryWStream stream;
SkImageEncoder::EncodeStream(&stream, b,
SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality);
- write(fd, stream.getStream(), stream.getOffset());
+ SkData* streamData = stream.copyToData();
+ write(fd, streamData->data(), streamData->size());
+ streamData->unref();
} else {
write(fd, &w, 4);
write(fd, &h, 4);
diff --git a/core/java/android/animation/TimeAnimator.java b/core/java/android/animation/TimeAnimator.java
index 0a96d59..a79f2a3 100644
--- a/core/java/android/animation/TimeAnimator.java
+++ b/core/java/android/animation/TimeAnimator.java
@@ -1,13 +1,11 @@
package android.animation;
/**
- * This class provides a simple callback mechanism to listeners that is synchronized with other
- * animators in the system. There is no duration, interpolation, or object value-setting
- * with this Animator. Instead, it is simply started and proceeds to send out events on every
- * animation frame to its TimeListener (if set), with information about this animator,
- * the total elapsed time, and the time since the last animation frame.
- *
- * @hide
+ * This class provides a simple callback mechanism to listeners that is synchronized with all
+ * other animators in the system. There is no duration, interpolation, or object value-setting
+ * with this Animator. Instead, it is simply started, after which it proceeds to send out events
+ * on every animation frame to its TimeListener (if set), with information about this animator,
+ * the total elapsed time, and the elapsed time since the previous animation frame.
*/
public class TimeAnimator extends ValueAnimator {
@@ -59,10 +57,10 @@
* Implementors of this interface can set themselves as update listeners
* to a <code>TimeAnimator</code> instance to receive callbacks on every animation
* frame to receive the total time since the animator started and the delta time
- * since the last frame. The first time the listener is called, totalTime and
- * deltaTime should both be zero.
- *
- * @hide
+ * since the last frame. The first time the listener is called,
+ * deltaTime will be zero. The same is true for totalTime, unless the animator was
+ * set to a specific {@link ValueAnimator#setCurrentPlayTime(long) currentPlayTime}
+ * prior to starting.
*/
public static interface TimeListener {
/**
@@ -70,7 +68,8 @@
* along with information about the elapsed time.</p>
*
* @param animation The animator sending out the notification.
- * @param totalTime The
+ * @param totalTime The total time elapsed since the animator started, in milliseconds.
+ * @param deltaTime The time elapsed since the previous frame, in milliseconds.
*/
void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime);
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index dfdea38..973fac1 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -44,6 +44,13 @@
*/
public final static int UNSUPPORTED = -1;
+ /** @hide */
+ public static final long KB_IN_BYTES = 1024;
+ /** @hide */
+ public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
+ /** @hide */
+ public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
+
/**
* Special UID value used when collecting {@link NetworkStatsHistory} for
* removed applications.
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index c86ea77..3ee275c 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -27,6 +27,10 @@
/**
* Coordinates animations and drawing for UI on a particular thread.
+ *
+ * This object is thread-safe. Other threads can add and remove listeners
+ * or schedule work to occur at a later time on the UI thread.
+ *
* @hide
*/
public final class Choreographer extends Handler {
@@ -44,7 +48,7 @@
private static final long DEFAULT_FRAME_DELAY = 10;
// The number of milliseconds between animation frames.
- private static long sFrameDelay = DEFAULT_FRAME_DELAY;
+ private static volatile long sFrameDelay = DEFAULT_FRAME_DELAY;
// Thread local storage for the choreographer.
private static final ThreadLocal<Choreographer> sThreadInstance =
@@ -75,6 +79,8 @@
private static final int MSG_DO_ANIMATION = 0;
private static final int MSG_DO_DRAW = 1;
+ private final Object mLock = new Object();
+
private final Looper mLooper;
private OnAnimateListener[] mOnAnimateListeners;
@@ -138,9 +144,14 @@
/**
* Schedules animation (and drawing) to occur on the next frame synchronization boundary.
- * Must be called on the UI thread.
*/
public void scheduleAnimation() {
+ synchronized (mLock) {
+ scheduleAnimationLocked();
+ }
+ }
+
+ private void scheduleAnimationLocked() {
if (!mAnimationScheduled) {
mAnimationScheduled = true;
if (USE_VSYNC) {
@@ -163,12 +174,14 @@
}
/**
- * Return true if {@link #scheduleAnimation()} has been called but
+ * Returns true if {@link #scheduleAnimation()} has been called but
* {@link OnAnimateListener#onAnimate() OnAnimateListener.onAnimate()} has
* not yet been called.
*/
public boolean isAnimationScheduled() {
- return mAnimationScheduled;
+ synchronized (mLock) {
+ return mAnimationScheduled;
+ }
}
/**
@@ -176,26 +189,30 @@
* Must be called on the UI thread.
*/
public void scheduleDraw() {
- if (!mDrawScheduled) {
- mDrawScheduled = true;
- if (USE_ANIMATION_TIMER_FOR_DRAW) {
- scheduleAnimation();
- } else {
- if (DEBUG) {
- Log.d(TAG, "Scheduling draw immediately.");
+ synchronized (mLock) {
+ if (!mDrawScheduled) {
+ mDrawScheduled = true;
+ if (USE_ANIMATION_TIMER_FOR_DRAW) {
+ scheduleAnimationLocked();
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Scheduling draw immediately.");
+ }
+ sendEmptyMessage(MSG_DO_DRAW);
}
- sendEmptyMessage(MSG_DO_DRAW);
}
}
}
/**
- * Return true if {@link #scheduleDraw()} has been called but
+ * Returns true if {@link #scheduleDraw()} has been called but
* {@link OnDrawListener#onDraw() OnDrawListener.onDraw()} has
* not yet been called.
*/
public boolean isDrawScheduled() {
- return mDrawScheduled;
+ synchronized (mLock) {
+ return mDrawScheduled;
+ }
}
@Override
@@ -211,60 +228,75 @@
}
private void doAnimation() {
- if (mAnimationScheduled) {
- mAnimationScheduled = false;
-
- final long start = SystemClock.uptimeMillis();
- if (DEBUG) {
- Log.d(TAG, "Performing animation: " + Math.max(0, start - mLastAnimationTime)
- + " ms have elapsed since previous animation.");
- }
- mLastAnimationTime = start;
-
- final OnAnimateListener[] listeners = mOnAnimateListeners;
- if (listeners != null) {
- for (int i = 0; i < listeners.length; i++) {
- listeners[i].onAnimate();
- }
- }
-
- if (DEBUG) {
- Log.d(TAG, "Animation took " + (SystemClock.uptimeMillis() - start) + " ms.");
- }
- }
+ doAnimationInner();
if (USE_ANIMATION_TIMER_FOR_DRAW) {
doDraw();
}
}
+ private void doAnimationInner() {
+ final long start;
+ final OnAnimateListener[] listeners;
+ synchronized (mLock) {
+ if (!mAnimationScheduled) {
+ return; // no work to do
+ }
+ mAnimationScheduled = false;
+
+ start = SystemClock.uptimeMillis();
+ if (DEBUG) {
+ Log.d(TAG, "Performing animation: " + Math.max(0, start - mLastAnimationTime)
+ + " ms have elapsed since previous animation.");
+ }
+ mLastAnimationTime = start;
+
+ listeners = mOnAnimateListeners;
+ }
+
+ if (listeners != null) {
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onAnimate();
+ }
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "Animation took " + (SystemClock.uptimeMillis() - start) + " ms.");
+ }
+ }
+
private void doDraw() {
- if (mDrawScheduled) {
+ final long start;
+ final OnDrawListener[] listeners;
+ synchronized (mLock) {
+ if (!mDrawScheduled) {
+ return; // no work to do
+ }
mDrawScheduled = false;
- final long start = SystemClock.uptimeMillis();
+ start = SystemClock.uptimeMillis();
if (DEBUG) {
Log.d(TAG, "Performing draw: " + Math.max(0, start - mLastDrawTime)
+ " ms have elapsed since previous draw.");
}
mLastDrawTime = start;
- final OnDrawListener[] listeners = mOnDrawListeners;
- if (listeners != null) {
- for (int i = 0; i < listeners.length; i++) {
- listeners[i].onDraw();
- }
- }
+ listeners = mOnDrawListeners;
+ }
- if (DEBUG) {
- Log.d(TAG, "Draw took " + (SystemClock.uptimeMillis() - start) + " ms.");
+ if (listeners != null) {
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onDraw();
}
}
+
+ if (DEBUG) {
+ Log.d(TAG, "Draw took " + (SystemClock.uptimeMillis() - start) + " ms.");
+ }
}
/**
* Adds an animation listener.
- * Must be called on the UI thread.
*
* @param listener The listener to add.
*/
@@ -277,13 +309,14 @@
Log.d(TAG, "Adding onAnimate listener: " + listener);
}
- mOnAnimateListeners = ArrayUtils.appendElement(OnAnimateListener.class,
- mOnAnimateListeners, listener);
+ synchronized (mLock) {
+ mOnAnimateListeners = ArrayUtils.appendElement(OnAnimateListener.class,
+ mOnAnimateListeners, listener);
+ }
}
/**
* Removes an animation listener.
- * Must be called on the UI thread.
*
* @param listener The listener to remove.
*/
@@ -296,14 +329,15 @@
Log.d(TAG, "Removing onAnimate listener: " + listener);
}
- mOnAnimateListeners = ArrayUtils.removeElement(OnAnimateListener.class,
- mOnAnimateListeners, listener);
- stopTimingLoopIfNoListeners();
+ synchronized (mLock) {
+ mOnAnimateListeners = ArrayUtils.removeElement(OnAnimateListener.class,
+ mOnAnimateListeners, listener);
+ stopTimingLoopIfNoListenersLocked();
+ }
}
/**
* Adds a draw listener.
- * Must be called on the UI thread.
*
* @param listener The listener to add.
*/
@@ -316,8 +350,10 @@
Log.d(TAG, "Adding onDraw listener: " + listener);
}
- mOnDrawListeners = ArrayUtils.appendElement(OnDrawListener.class,
- mOnDrawListeners, listener);
+ synchronized (mLock) {
+ mOnDrawListeners = ArrayUtils.appendElement(OnDrawListener.class,
+ mOnDrawListeners, listener);
+ }
}
/**
@@ -335,12 +371,14 @@
Log.d(TAG, "Removing onDraw listener: " + listener);
}
- mOnDrawListeners = ArrayUtils.removeElement(OnDrawListener.class,
- mOnDrawListeners, listener);
- stopTimingLoopIfNoListeners();
+ synchronized (mLock) {
+ mOnDrawListeners = ArrayUtils.removeElement(OnDrawListener.class,
+ mOnDrawListeners, listener);
+ stopTimingLoopIfNoListenersLocked();
+ }
}
- private void stopTimingLoopIfNoListeners() {
+ private void stopTimingLoopIfNoListenersLocked() {
if (mOnDrawListeners == null && mOnAnimateListeners == null) {
if (DEBUG) {
Log.d(TAG, "Stopping timing loop.");
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7ba17b3..8d32edc 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2166,15 +2166,13 @@
float mScaleY = 1f;
/**
- * The amount of scale in the x direction around the pivot point. A
- * value of 1 means no scaling is applied.
+ * The x location of the point around which the view is rotated and scaled.
*/
@ViewDebug.ExportedProperty
float mPivotX = 0f;
/**
- * The amount of scale in the y direction around the pivot point. A
- * value of 1 means no scaling is applied.
+ * The y location of the point around which the view is rotated and scaled.
*/
@ViewDebug.ExportedProperty
float mPivotY = 0f;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index dcddd47..fbafc64 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2654,7 +2654,7 @@
checkThread();
mContentWidth = 0;
mContentHeight = 0;
- setBaseLayer(0, null, false, false, false);
+ setBaseLayer(0, null, false, false);
mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
}
@@ -2822,6 +2822,34 @@
return result;
}
+ int getBlockLeftEdge(int x, int y, float readingScale) {
+ if (!sDisableNavcache) {
+ return nativeGetBlockLeftEdge(x, y, readingScale);
+ }
+
+ float invReadingScale = 1.0f / readingScale;
+ int readingWidth = (int) (getViewWidth() * invReadingScale);
+ int left = NO_LEFTEDGE;
+ if (mFocusedNode != null) {
+ final int length = mFocusedNode.mEnclosingParentRects.length;
+ for (int i = 0; i < length; i++) {
+ Rect rect = mFocusedNode.mEnclosingParentRects[i];
+ if (rect.width() < mFocusedNode.mHitTestSlop) {
+ // ignore bounding boxes that are too small
+ continue;
+ } else if (left != NO_LEFTEDGE && rect.width() > readingWidth) {
+ // stop when bounding box doesn't fit the screen width
+ // at reading scale
+ break;
+ }
+
+ left = rect.left;
+ }
+ }
+
+ return left;
+ }
+
// Called by JNI when the DOM has changed the focus. Clear the focus so
// that new keys will go to the newly focused field
private void domChangedFocus() {
@@ -4521,6 +4549,8 @@
if (canvas.isHardwareAccelerated()) {
mZoomManager.setHardwareAccelerated();
+ } else {
+ mWebViewCore.resumeWebKitDraw();
}
int saveCount = canvas.save();
@@ -4763,11 +4793,19 @@
}
void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator,
- boolean isPictureAfterFirstLayout, boolean registerPageSwapCallback) {
+ boolean isPictureAfterFirstLayout) {
if (mNativeClass == 0)
return;
- nativeSetBaseLayer(mNativeClass, layer, invalRegion, showVisualIndicator,
- isPictureAfterFirstLayout, registerPageSwapCallback);
+ boolean queueFull;
+ queueFull = nativeSetBaseLayer(mNativeClass, layer, invalRegion,
+ showVisualIndicator, isPictureAfterFirstLayout);
+
+ if (layer == 0 || isPictureAfterFirstLayout) {
+ mWebViewCore.resumeWebKitDraw();
+ } else if (queueFull) {
+ mWebViewCore.pauseWebKitDraw();
+ }
+
if (mHTML5VideoViewProxy != null) {
mHTML5VideoViewProxy.setBaseLayer(layer);
}
@@ -9049,6 +9087,7 @@
/** @hide Called by JNI when pages are swapped (only occurs with hardware
* acceleration) */
protected void pageSwapCallback(boolean notifyAnimationStarted) {
+ mWebViewCore.resumeWebKitDraw();
if (inEditingMode()) {
didUpdateWebTextViewDimensions(ANYWHERE);
}
@@ -9071,13 +9110,9 @@
boolean isPictureAfterFirstLayout = viewState != null;
if (updateBaseLayer) {
- // Request a callback on pageSwap (to reposition the webtextview)
- boolean registerPageSwapCallback =
- !mZoomManager.isFixedLengthAnimationInProgress() && inEditingMode();
-
setBaseLayer(draw.mBaseLayer, draw.mInvalRegion,
getSettings().getShowVisualIndicator(),
- isPictureAfterFirstLayout, registerPageSwapCallback);
+ isPictureAfterFirstLayout);
}
final Point viewSize = draw.mViewSize;
// We update the layout (i.e. request a layout from the
@@ -9755,11 +9790,6 @@
}
}
- /** @hide call pageSwapCallback upon next page swap */
- protected void registerPageSwapCallback() {
- nativeRegisterPageSwapCallback(mNativeClass);
- }
-
/** @hide discard all textures from tiles */
protected void discardAllTextures() {
nativeDiscardAllTextures();
@@ -9922,10 +9952,9 @@
private native void nativeSetFindIsEmpty();
private native void nativeSetFindIsUp(boolean isUp);
private native void nativeSetHeightCanMeasure(boolean measure);
- private native void nativeSetBaseLayer(int nativeInstance,
+ private native boolean nativeSetBaseLayer(int nativeInstance,
int layer, Region invalRegion,
- boolean showVisualIndicator, boolean isPictureAfterFirstLayout,
- boolean registerPageSwapCallback);
+ boolean showVisualIndicator, boolean isPictureAfterFirstLayout);
private native int nativeGetBaseLayer();
private native void nativeShowCursorTimed();
private native void nativeReplaceBaseContent(int content);
@@ -9937,7 +9966,6 @@
private native void nativeStopGL();
private native Rect nativeSubtractLayers(Rect content);
private native int nativeTextGeneration();
- private native void nativeRegisterPageSwapCallback(int nativeInstance);
private native void nativeDiscardAllTextures();
private native void nativeTileProfilingStart();
private native float nativeTileProfilingStop();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 8582dbc..8a9c12d 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -872,6 +872,7 @@
Rect[] mTouchRects;
boolean mEditable;
int mTapHighlightColor = WebView.HIGHLIGHT_COLOR;
+ Rect[] mEnclosingParentRects;
// These are the input values that produced this hit test
int mHitTestX;
@@ -2169,7 +2170,36 @@
.obtainMessage(WebView.INVAL_RECT_MSG_ID));
}
+ private Boolean m_skipDrawFlag = false;
+ private boolean m_drawWasSkipped = false;
+
+ void pauseWebKitDraw() {
+ synchronized (m_skipDrawFlag) {
+ if (!m_skipDrawFlag) {
+ m_skipDrawFlag = true;
+ }
+ }
+ }
+
+ void resumeWebKitDraw() {
+ synchronized (m_skipDrawFlag) {
+ if (m_skipDrawFlag && m_drawWasSkipped) {
+ // a draw was dropped, send a retry
+ m_drawWasSkipped = false;
+ mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
+ }
+ m_skipDrawFlag = false;
+ }
+ }
+
private void webkitDraw() {
+ synchronized (m_skipDrawFlag) {
+ if (m_skipDrawFlag) {
+ m_drawWasSkipped = true;
+ return;
+ }
+ }
+
mDrawIsScheduled = false;
DrawData draw = new DrawData();
if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw start");
@@ -2178,7 +2208,7 @@
if (draw.mBaseLayer == 0) {
if (mWebView != null && !mWebView.isPaused()) {
if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, resending draw message");
- mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
+ mEventHub.sendMessageDelayed(Message.obtain(null, EventHub.WEBKIT_DRAW), 10);
} else {
if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, webview paused");
}
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 8ffba64..ae2d617 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -717,7 +717,7 @@
private void zoomToReadingLevel() {
final float readingScale = getReadingLevelScale();
- int left = mWebView.nativeGetBlockLeftEdge(mAnchorX, mAnchorY, mActualScale);
+ int left = mWebView.getBlockLeftEdge(mAnchorX, mAnchorY, readingScale);
if (left != WebView.NO_LEFTEDGE) {
// add a 5pt padding to the left edge.
int viewLeft = mWebView.contentToViewX(left < 5 ? 0 : (left - 5))
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 23ee8f8..ef6af74 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -67,7 +67,7 @@
static void freeCaches(JNIEnv* env, jobject) {
// these are called in no particular order
SkImageRef_GlobalPool::SetRAMUsed(0);
- SkGraphics::SetFontCacheUsed(0);
+ SkGraphics::PurgeFontCache();
}
static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index a1997a2..7f5d54d 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -29,7 +29,10 @@
namespace android {
//--------------------------------------------------------------------------------------------------
-#define TYPEFACE_ARABIC "/system/fonts/DroidNaskh-Regular.ttf"
+// Using DroidSansArabic for shaping Arabic with Harfbuzz because its metrics are more compatible
+// with the "Roboto" metrics (compared to DroidNaskh-Regular). When we will have an Arabic font
+// whose metrics are similar to the Roboto ones, then we will need to use it for shaping.
+#define TYPEFACE_ARABIC "/system/fonts/DroidSansArabic.ttf"
#define TYPE_FACE_HEBREW_REGULAR "/system/fonts/DroidSansHebrew-Regular.ttf"
#define TYPE_FACE_HEBREW_BOLD "/system/fonts/DroidSansHebrew-Bold.ttf"
#define TYPEFACE_BENGALI "/system/fonts/Lohit-Bengali.ttf"
diff --git a/core/res/lint.xml b/core/res/lint.xml
new file mode 100644
index 0000000..822cdd7
--- /dev/null
+++ b/core/res/lint.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+ <!-- temporary until we add frameworks support -->
+ <issue id="UnusedResources" severity="ignore" />
+
+ <issue id="PrivateResource" severity="ignore" />
+</lint>
\ No newline at end of file
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 1068b66..56af9aa 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -785,7 +785,7 @@
</plurals>
<plurals name="num_minutes_ago">
<item quantity="one" msgid="3306787433088810191">"iminithi elingu-1 edlule"</item>
- <item quantity="other" msgid="2176942008915455116">"amaminithi angu-<xliff:g id="COUNT">%d</xliff:g> adlule.."</item>
+ <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> amaminithi adlule.."</item>
</plurals>
<plurals name="num_hours_ago">
<item quantity="one" msgid="9150797944610821849">"ihora elingu-1 elidlule"</item>
@@ -822,7 +822,7 @@
</plurals>
<plurals name="abbrev_num_minutes_ago">
<item quantity="one" msgid="6361490147113871545">"iminithi elingu-1 edlule"</item>
- <item quantity="other" msgid="851164968597150710">"amaminithi angu-<xliff:g id="COUNT">%d</xliff:g> adlule"</item>
+ <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> amaminithi adlule"</item>
</plurals>
<plurals name="abbrev_num_hours_ago">
<item quantity="one" msgid="4796212039724722116">"ihora elingu-1 elidlule"</item>
@@ -1111,7 +1111,7 @@
<string name="no_matches" msgid="8129421908915840737">"Akukho okufanayo"</string>
<string name="find_on_page" msgid="1946799233822820384">"Thola ekhasini"</string>
<plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"okufanayo okungu-1"</item>
+ <item quantity="one" msgid="8167147081136579439">"1 okufanayo"</item>
<item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ku-<xliff:g id="TOTAL">%d</xliff:g>"</item>
</plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Kwenziwe"</string>
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
index 1df763a..b181122 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
@@ -24,6 +24,8 @@
import static android.net.NetworkStatsHistory.DataStreamUtils.readVarLong;
import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLong;
import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
+import static android.net.TrafficStats.GB_IN_BYTES;
+import static android.net.TrafficStats.MB_IN_BYTES;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -50,10 +52,6 @@
private static final long TEST_START = 1194220800000L;
- private static final long KB_IN_BYTES = 1024;
- private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
- private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
-
private NetworkStatsHistory stats;
@Override
diff --git a/data/fonts/DroidSansArabic.ttf b/data/fonts/DroidSansArabic.ttf
new file mode 100644
index 0000000..bdefaac
--- /dev/null
+++ b/data/fonts/DroidSansArabic.ttf
Binary files differ
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 47cdae7..044de2f 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -25,6 +25,7 @@
<familyset>
<family>
<fileset>
+ <file>DroidSansArabic.ttf</file>
<file>DroidNaskh-Regular.ttf</file>
</fileset>
</family>
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 9dca329..6a9ed53 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -21,6 +21,7 @@
frameworks/base/data/fonts/Roboto-Bold.ttf:system/fonts/Roboto-Bold.ttf \
frameworks/base/data/fonts/Roboto-Italic.ttf:system/fonts/Roboto-Italic.ttf \
frameworks/base/data/fonts/Roboto-BoldItalic.ttf:system/fonts/Roboto-BoldItalic.ttf \
+ frameworks/base/data/fonts/DroidSansArabic.ttf:system/fonts/DroidSansArabic.ttf \
frameworks/base/data/fonts/DroidNaskh-Regular.ttf:system/fonts/DroidNaskh-Regular.ttf \
frameworks/base/data/fonts/DroidSansHebrew-Regular.ttf:system/fonts/DroidSansHebrew-Regular.ttf \
frameworks/base/data/fonts/DroidSansHebrew-Bold.ttf:system/fonts/DroidSansHebrew-Bold.ttf \
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index e46d07c..d390ec1 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -254,6 +254,10 @@
<td><code>04DD</code></td>
</tr>
<tr>
+ <td>Sony</td>
+ <td><code>054C</code></td>
+ </tr>
+ <tr>
<td>Sony Ericsson</td>
<td><code>0FCE</code></td>
</tr>
diff --git a/docs/html/guide/practices/tablets-and-handsets.jd b/docs/html/guide/practices/tablets-and-handsets.jd
index 3f4aaa9..8e07a08 100644
--- a/docs/html/guide/practices/tablets-and-handsets.jd
+++ b/docs/html/guide/practices/tablets-and-handsets.jd
@@ -99,7 +99,8 @@
<p>You can enable items from the options menu to appear directly in the action bar as "action
items". You can also add navigation features to the action bar, such as tabs or a drop-down list,
-and use the application icon to supplement the system's BACK behavior with the option to navigate to
+and use the application icon to supplement the system's <em>Back</em> button behavior with the option to
+navigate to
your application's "home" activity or "up" the application's structural hierarchy.</p>
<p>This guide provides some tips for using the action bar in ways that support both tablets and
@@ -458,7 +459,8 @@
developer guide, you can use the application icon in the action bar to facilitate user navigation
when appropriate—either as a method to get back to the "home" activity (similar to clicking
the logo on a web site) or as a way to navigate up the application's structural hierarchy. Although
-it might seem similar to the standard BACK navigation in some cases, the up navigation option
+it might seem similar to the standard <em>Back</em> navigation in some cases, the up navigation
+option
provides a more predictable navigation method for situations in which the user may have entered
from an external location, such as a notification, app widget, or a different application.</p>
diff --git a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
index 5faa7ec..9be72ee 100644
--- a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
@@ -42,7 +42,8 @@
<li><a href=#activities_added_to_task_tip>Allow activities to add to current task</a></li>
<li><a href=#notifications_get_back_tip>Notifications and App Widgets should provide consistent back behavior</li>
<li><a href=#use_notification_tip>Use the notification system</a></li>
- <li><a href=#taking_over_back_key>Don't take over BACK key unless you absolutely need to</a></li>
+ <li><a href=#taking_over_back_key>Don't take over <em>Back</em> button unless you absolutely
+need to</a></li>
</ol>
</li>
</ol>
@@ -241,8 +242,8 @@
Android system keeps a linear navigation history of activities the
user has visited. This is the <em>activity stack</em>, also known as the
back stack. In general, when a user starts a new activity, it is added
- to the activity stack, so that pressing BACK displays the previous
- activity on the stack. However, the user cannot use the BACK key to go
+ to the activity stack, so that pressing <em>Back</em> displays the previous
+ activity on the stack. However, the user cannot use the <em>Back</em> button to go
back further than the last visit to Home. The adding of an activity to
the current stack happens whether or not that activity begins a new
<a href=#tasks title=task>task</a> (as long as that task was started
@@ -256,10 +257,11 @@
Activities are the only things that can be added to the activity stack
— views, windows, menus, and dialogs cannot. That is, when
designing the navigation, if you have screen A and you want the user
- to be able go to a subsequent screen B and then use the BACK key to go
+ to be able go to a subsequent screen B and then use the <em>Back</em> button to go
back to screen A, then the screen A needs to be implemented as an
activity. The one exception to this rule is if your application
- <a href="#taking_over_back_key">takes control of the BACK key</a> and manages the navigation
+ <a href="#taking_over_back_key">takes control of the <em>Back</em> button</a> and manages the
+navigation
itself.
</p>
@@ -287,7 +289,7 @@
launcher, Home screen shortcut or "Recent tasks" switcher (a long
press on Home on some devices). The user can return to a task by
choosing the icon for its root activity the same way they started the
- task. Once inside a task, the BACK key goes to previous activities in
+ task. Once inside a task, the <em>Back</em> button goes to previous activities in
that task. The activity stack is made up of one or more tasks.
</p>
@@ -331,7 +333,7 @@
Browser are two applications that do this. For example, choosing an
address in an email starts the Maps activity as a new task, and
choosing a link in an email starts the Browser activity as a new
- task. In these cases, the BACK key will return to the previous
+ task. In these cases, the <em>Back</em> button will return to the previous
activity in a different task (Email), because it was not started from
Home.
</p>
@@ -341,7 +343,7 @@
<p>
The following examples illustrate basic principles for applications,
- activities, the activity stack, the BACK key, tasks and intents. It
+ activities, the activity stack, the <em>Back</em> button, tasks and intents. It
shows how the system responds to user actions such as starting
activities and switching between tasks. With most of these examples
you can follow along, launching activities on your device as
@@ -367,19 +369,20 @@
<img src={@docRoot}images/activity_task_design/HomeTaskBasics1a.png>
</p>
-<h3 id=navigating_away_from_an_activity>Navigating Away from an Activity with BACK and HOME keys</h3>
+<h3 id=navigating_away_from_an_activity>Navigating Away from an Activity with <em>Back</em> and
+<em>Home</em> buttons</h3>
<p>
An activity can keep or lose its state depending on how the user
- leaves the activity — by the HOME or BACK key.
+ leaves the activity — by the <em>Home</em> or <em>Back</em> button.
</p>
<p>
- By default, pressing the BACK key finishes (destroys) the current
+ By default, pressing the <em>Back</em> button finishes (destroys) the current
activity and displays the previous activity to the user. In the
following figure, the user starts email by touching the Email icon in
the Home screen, which displays a list of email messages. The user
- scrolls down the list (changing its initial state). Pressing BACK
+ scrolls down the list (changing its initial state). Pressing <em>Back</em>
destroys the List Messages activity and returns to the previous
activity, which is Home. If the user re-launches Email, it would
re-load the messages and display its initial, non-scrolled state.
@@ -390,15 +393,15 @@
</p>
<p>
- In the above example, pressing BACK goes to Home because it was the
+ In the above example, pressing <em>Back</em> goes to Home because it was the
last activity the user was viewing. But if the user had gotten to List
- Message from some other activity, then pressing BACK would have
+ Message from some other activity, then pressing <em>Back</em> would have
returned there.
</p>
<p>
By contrast, the next figure shows the user leaving List Messages by
- pressing HOME instead of BACK — the List Messages activity is
+ pressing <em>Home</em> instead of <em>Back</em> — the List Messages activity is
stopped and moved to the background rather than being
destroyed. Starting Email again from its icon would simply bring the
List Messages activity to the foreground (changing it from stopped to
@@ -423,8 +426,8 @@
<p>
In addition, not all activities have the behavior that they are
- destroyed when BACK is pressed. When the user starts playing music in
- the Music application and then presses BACK, the application overrides
+ destroyed when <em>Back</em> is pressed. When the user starts playing music in
+ the Music application and then presses <em>Back</em>, the application overrides
the normal back behavior, preventing the player activity from being
destroyed, and continues playing music, even though its activity is no
longer visible — as a visual substitute, the Music application
@@ -451,7 +454,7 @@
activity to get a picture. This is a good example of re-use of the
Gallery activity. The following figure illustrates the sequence of
activities to do this (up to crop). This is how it's done: The user
- chooses Contacts, selects the contact for viewing, chooses MENU >
+ chooses Contacts, selects the contact for viewing, chooses <em>Menu</em> >
Edit contact and touches the picture field, which launches the Gallery
activity. The user then chooses the picture they want, crops and saves
it. Saving it causes the picture to be inserted into the picture field
@@ -484,12 +487,12 @@
<b>Gallery Re-Uses Messaging for Sharing a Picture</b> - Sharing is
another good example of one application re-using an activity from a
different application. As shown in the following figure, the user
- starts Gallery, picks a picture to view, chooses MENU > Share, and
+ starts Gallery, picks a picture to view, chooses <em>Menu</em> > Share, and
picks "Messaging". This starts the Messaging activity, creates a new
message and attaches the original picture to it. The user then fills
in the "To" field, writes a short message and sends it. User focus
remains in the Messaging program. If the user wants to go back to the
- Gallery, they must press the BACK key. (The user can back up through
+ Gallery, they must press the <em>Back</em> button. (The user can back up through
each activity all the way to Home.)
</p>
@@ -552,7 +555,7 @@
<ul>
<li>
State 2 - The user wants to do something else while they're
- waiting, so they press HOME, which does not interrupt the map's
+ waiting, so they press <em>Home</em>, which does not interrupt the map's
network connection and allows the map to continue loading in the
background.
@@ -729,7 +732,7 @@
<b>Start first task.</b> You want to send a text message and attach a photo. You would choose:
<p>
- Home > Messaging > New message > MENU > Attach
+ Home > Messaging > New message > <em>Menu</em> > Attach
> Pictures. This last step launches the picture gallery
for picking a photo. Notice that picture gallery is an
activity in a separate application.
@@ -961,7 +964,7 @@
address in an email message (or web page), where the Maps
activity is started to map the location. No result from maps
is expected to be returned to the email message; the user
- can return by pressing the BACK key. (Such an activity is
+ can return by pressing the <em>Back</em> button. (Such an activity is
started with {@link
android.content.Context#startActivity(android.content.Intent)
startActivity()}.)
@@ -1102,20 +1105,21 @@
convenience to respond to your message.
</p>
-<h3 id=taking_over_back_key>Don't take over the BACK key unless you absolutely need to</h3>
+<h3 id=taking_over_back_key>Don't take over the <em>Back</em> button unless you absolutely need
+to</h3>
<p>
As a user navigates from one activity to the next, the system adds
them to the activity stack. This forms a navigation history that is
- accessible with the BACK key. Most activities are relatively limited
+ accessible with the <em>Back</em> button. Most activities are relatively limited
in scope, with just one set of data, such as viewing a list of
contacts, composing an email, or taking a photo. But what if your
application is one big activity with several pages of content and
- needs finer-grained control of the BACK key? Examples of such Google
+ needs finer-grained control of the <em>Back</em> button? Examples of such Google
applications are the Browser, which can have several web pages open
at once, and Maps, which can have several layers of geographic data
to switch between. Both of these applications take control of the
- BACK key and maintain their own internal back stacks that operate
+ <em>Back</em> button and maintain their own internal back stacks that operate
only when these applications have focus.
</p>
@@ -1124,7 +1128,7 @@
information on a map to the user: displaying the location of a
search result, displaying locations of friends, and displaying a
line for a street path providing direction between points. Maps
- stores these layers in its own history so the BACK key can return to
+ stores these layers in its own history so the <em>Back</em> button can return to
a previous layer.
</p>
@@ -1135,8 +1139,8 @@
as Windows, Macintosh or Linux). For example, if you did a Google
web search in one window of the Android Browser, clicking on a link
in the search results displays a web page in that same window, and
- then pressing BACK would to the search results page. Pressing
- BACK goes to a previous window only if the current window was
+ then pressing <em>Back</em> would to the search results page. Pressing
+ <em>Back</em> goes to a previous window only if the current window was
launched from that previous window. If the user keeps pressing
back, they will eventually leave the browser activity and return
Home.
diff --git a/docs/html/guide/practices/ui_guidelines/menu_design.jd b/docs/html/guide/practices/ui_guidelines/menu_design.jd
index 3edf33f..7576b6c 100644
--- a/docs/html/guide/practices/ui_guidelines/menu_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/menu_design.jd
@@ -71,7 +71,7 @@
<ul>
<li>The <em>Options menu</em> contains primary functionality that applies
globally to the current activity or starts a related activity.
- It is typically invoked by a user pressing a hard button, often labeled MENU.</li>
+ It is typically invoked by a user pressing a hard button, often labeled <em>Menu</em>.</li>
<li>The <em>Context menu</em> contains secondary functionality for the currently
selected item. It is typically invoked by a user's touch & hold
on an item. Like on the Options menu, the operation can run either
@@ -109,10 +109,10 @@
</p>
<p>
- On most devices, a user presses the MENU button to access the Options menu,
+ On most devices, a user presses the <em>Menu</em> button to access the Options menu,
as shown in the screenshot below. To close the menu, the user presses
- MENU again, or presses the BACK button.
- In fact, to cancel out of any menu, press the BACK button. (Pressing the MENU
+ <em>Menu</em> again, or presses the <em>Back</em> button.
+ In fact, to cancel out of any menu, press the <em>Back</em> button. (Pressing the <em>Menu</em>
button or touching outside the menu also works.) Note that how to invoke this
menu may be different on different devices.
</p>
@@ -140,7 +140,7 @@
<ul>
<li>
- <b>Options icon menu</b> - The first press of the MENU button displays a
+ <b>Options icon menu</b> - The first press of the <em>Menu</em> button displays a
non-scrollable grid of icons at the bottom of the screen. (On the G1
phone, up to 6 buttons typically appear.)
</li>
@@ -156,7 +156,7 @@
<p>
On some versions of Android, the user can display keyboard shortcuts in the
- icon menu by long pressing the MENU button — the text in the icon menu
+ icon menu by long pressing the <em>Menu</em> button — the text in the icon menu
alternates between the command names and their keyboard shortcuts (if any).
</p>
@@ -299,7 +299,7 @@
<a href="#location">location</a>) on the screen, put the command in the
Context menu for that content. If the command acts on no specific content
or location, put it in the Options menu. This separation of commands
- is enforced by the system in the following way. When you press the MENU
+ is enforced by the system in the following way. When you press the <em>Menu</em>
button to display the Options menu, the selected content becomes unselected,
and so cannot be operated on. For an explanation
of why the content becomes unselected, see the article on
@@ -340,7 +340,7 @@
<p>
Before opening a Context menu, it has no visual representation that identifies
- its presence (whereas the Options menu has the MENU button), and so is not
+ its presence (whereas the Options menu has the <em>Menu</em> button), and so is not
particularly discoverable.
Therefore, in general, a Context menu should <em>duplicate</em> commands
found in the corresponding activity screen. For example, while it's useful to
@@ -459,7 +459,8 @@
<h3 id="a_dialog_should_not_have_an_options_menu">A dialog should not have an Options menu</h3>
<p>
- When a dialog is displayed, pressing the MENU button should do nothing. This also holds true
+ When a dialog is displayed, pressing the <em>Menu</em> button should do nothing. This also holds
+true
for activities that look like dialogs. A dialog box is recognizable by being
smaller than full-screen, having zero to three buttons, is non-scrollable, and
possibly a list of selectable items that can include checkboxes or radio buttons.
@@ -475,7 +476,7 @@
<h3 id="do_not_substitute_message">If an activity has no Options menu, do not display a message</h3>
<p>
- When the user presses the MENU button, if there is no Options menu, the system
+ When the user presses the <em>Menu</em> button, if there is no Options menu, the system
currently does nothing. We recommend you do not perform any action (such as
displaying a message). It's a better user experience for this behavior to be
consistent across applications.
diff --git a/docs/html/guide/topics/fundamentals/activities.jd b/docs/html/guide/topics/fundamentals/activities.jd
index 3b31199..8736aa8 100644
--- a/docs/html/guide/topics/fundamentals/activities.jd
+++ b/docs/html/guide/topics/fundamentals/activities.jd
@@ -63,7 +63,7 @@
activity starts, the previous activity is stopped, but the system preserves the activity
in a stack (the "back stack"). When a new activity starts, it is pushed onto the back stack and
takes user focus. The back stack abides to the basic "last in, first out" queue mechanism,
-so, when the user is done with the current activity and presses the BACK key, it
+so, when the user is done with the current activity and presses the <em>Back</em> button, it
is popped from the stack (and destroyed) and the previous activity resumes. (The back stack is
discussed more in the <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks
and Back Stack</a> document.)</p>
@@ -649,7 +649,8 @@
<p class="note"><strong>Note:</strong> There's no guarantee that {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} will be called before your
activity is destroyed, because there are cases in which it won't be necessary to save the state
-(such as when the user leaves your activity using the BACK key, because the user is explicitly
+(such as when the user leaves your activity using the <em>Back</em> button, because the user is
+explicitly
closing the activity). If the system calls {@link android.app.Activity#onSaveInstanceState
onSaveInstanceState()}, it does so before {@link
android.app.Activity#onStop onStop()} and possibly before {@link android.app.Activity#onPause
diff --git a/docs/html/guide/topics/fundamentals/fragments.jd b/docs/html/guide/topics/fundamentals/fragments.jd
index e8f6cd8..d4f9342 100644
--- a/docs/html/guide/topics/fundamentals/fragments.jd
+++ b/docs/html/guide/topics/fundamentals/fragments.jd
@@ -78,7 +78,7 @@
fragment transaction, you can also add it to a back stack that's managed by the
activity—each back stack entry in the activity is a record of the fragment transaction that
occurred. The back stack allows the user to reverse a fragment transaction (navigate backwards),
-by pressing the BACK button.</p>
+by pressing the <em>Back</em> button.</p>
<p>When you add a fragment as a part of your activity layout, it lives in a {@link
android.view.ViewGroup} inside the activity's view hierarchy and the fragment defines its own view
@@ -398,7 +398,7 @@
the activity layout) or {@link android.app.FragmentManager#findFragmentByTag
findFragmentByTag()} (for fragments that do or don't provide a UI).</li>
<li>Pop fragments off the back stack, with {@link
-android.app.FragmentManager#popBackStack()} (simulating a BACK command by the user).</li>
+android.app.FragmentManager#popBackStack()} (simulating a <em>Back</em> command by the user).</li>
<li>Register a listener for changes to the back stack, with {@link
android.app.FragmentManager#addOnBackStackChangedListener addOnBackStackChangedListener()}.</li>
</ul>
@@ -439,7 +439,7 @@
android.app.FragmentTransaction#commit()}, however, you might want to call {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()}, in order to add the transaction
to a back stack of fragment transactions. This back stack is managed by the activity and allows
-the user to return to the previous fragment state, by pressing the BACK key.</p>
+the user to return to the previous fragment state, by pressing the <em>Back</em> button.</p>
<p>For example, here's how you can replace one fragment with another, and preserve the previous
state in the back stack:</p>
@@ -462,14 +462,14 @@
layout container identified by the {@code R.id.fragment_container} ID. By calling {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()}, the replace transaction is
saved to the back stack so the user can reverse the transaction and bring back the
-previous fragment by pressing the BACK key.</p>
+previous fragment by pressing the <em>Back</em> button.</p>
<p>If you add multiple changes to the transaction (such as another {@link
android.app.FragmentTransaction#add add()} or {@link android.app.FragmentTransaction#remove
remove()}) and call {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()}, then all changes applied
before you call {@link android.app.FragmentTransaction#commit commit()} are added to the
-back stack as a single transaction and the BACK key will reverse them all together.</p>
+back stack as a single transaction and the <em>Back</em> button will reverse them all together.</p>
<p>The order in which you add changes to a {@link android.app.FragmentTransaction} doesn't matter,
except:</p>
@@ -696,7 +696,7 @@
<p>The most significant difference in lifecycle between an activity and a fragment is how one is
stored in its respective back stack. An activity is placed into a back stack of activities
that's managed by the system when it's stopped, by default (so that the user can navigate back
-to it with the BACK key, as discussed in <a
+to it with the <em>Back</em> button, as discussed in <a
href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a>).
However, a fragment is placed into a back stack managed by the host activity only when you
explicitly request that the instance be saved by calling {@link
diff --git a/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd b/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd
index 086ba71..465cf54 100644
--- a/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd
+++ b/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd
@@ -74,7 +74,7 @@
suppose you have a two-pane layout using fragments, one of which is a list view (fragment A) and the
other being a layout to display an item from the list (fragment B). When the user selects an item
from the list, fragment B is replaced by a new fragment (fragment C). In this case, it might be
-desireable for the user to navigate back to reveal fragment B, using the BACK button.</p>
+desireable for the user to navigate back to reveal fragment B, using the <em>Back</em> button.</p>
<p>In order to add fragment B to the back stack so that this is possible, you must call {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()} before you {@link
android.app.FragmentTransaction#commit()} the transaction that replaces fragment B with fragment
@@ -94,22 +94,26 @@
<p>When the current activity starts another, the new activity is pushed on the top of the stack and
takes focus. The previous activity remains in the stack, but is stopped. When an activity
-stops, the system retains the current state of its user interface. When the user presses the BACK
+stops, the system retains the current state of its user interface. When the user presses the
+<em>Back</em>
button, the current activity is popped from the top of the stack (the activity is destroyed) and the
previous activity resumes (the previous state of its UI is restored). Activities in the stack are
never rearranged, only pushed and popped from the stack—pushed onto the stack when started by
-the current activity and popped off when the user leaves it using the BACK button. As such, the back
+the current activity and popped off when the user leaves it using the <em>Back</em> button. As such,
+the back
stack operates as a "last in, first out" object structure. Figure 1 visualizes
this behavior with a timeline showing the progress between activities along with the current back
stack at each point in time.</p>
<img src="{@docRoot}images/fundamentals/diagram_backstack.png" alt="" />
<p class="img-caption"><strong>Figure 1.</strong> A representation of how each new activity in a
-task adds an item to the back stack. When the user presses the BACK button, the current activity is
+task adds an item to the back stack. When the user presses the <em>Back</em> button, the current
+activity is
destroyed and the previous activity resumes.</p>
-<p>If the user continues to press BACK, then each activity in the stack is popped off to reveal the
+<p>If the user continues to press <em>Back</em>, then each activity in the stack is popped off to
+reveal the
previous one, until the user returns to the Home screen (or to whichever activity was running when
the task began). When all activities are removed from the stack, the task no longer exists.</p>
@@ -124,11 +128,13 @@
</div>
<p>A task is a cohesive unit that can move to the "background" when users begin a new task or go
-to the Home screen, via the HOME button. While in the background, all the activities in the task are
+to the Home screen, via the <em>Home</em> button. While in the background, all the activities in the
+task are
stopped, but the back stack for the task remains intact—the task has simply lost focus while
another task takes place, as shown in figure 2. A task can then return to the "foreground" so users
can pick up where they left off. Suppose, for example, that the current task (Task A) has three
-activities in its stack—two under the current activity. The user presses the HOME button, then
+activities in its stack—two under the current activity. The user presses the <em>Home</em>
+button, then
starts a new application from the application launcher. When the Home screen appears, Task A goes
into the background. When the new application starts, the system starts a task for that application
(Task B) with its own stack of activities. After interacting with
@@ -137,7 +143,8 @@
foreground—all three activities in its stack are intact and the activity at the top of the
stack resumes. At
this point, the user can also switch back to Task B by going Home and selecting the application icon
-that started that task (or by touching and holding the HOME button to reveal recent tasks and selecting
+that started that task (or by touching and holding the <em>Home</em> button to reveal recent tasks
+and selecting
one). This is an example of multitasking on Android.</p>
<p class="note"><strong>Note:</strong> Multiple tasks can be held in the background at once.
@@ -150,7 +157,8 @@
that activity is created and popped onto the stack (rather than bringing any previous instance of
the activity to the top). As such, one activity in your application might be instantiated multiple
times (even from different tasks), as shown in figure 3. As such, if the user navigates backward
-using the BACK button, each instance of the activity is revealed in the order they were opened (each
+using the <em>Back</em> button, each instance of the activity is revealed in the order they were
+opened (each
with their own UI state). However, you can modify this behavior if you do not want an activity to be
instantiated more than once. How to do so is discussed in the later section about <a
href="#ManagingTasks">Managing Tasks</a>.</p>
@@ -161,13 +169,15 @@
<ul>
<li>When Activity A starts Activity B, Activity A is stopped, but the system retains its state
(such as scroll position and text entered into forms).
-If the user presses the BACK button while in Activity B, Activity A resumes with its state
+If the user presses the <em>Back</em> button while in Activity B, Activity A resumes with its state
restored.</li>
- <li>When the user leaves a task by pressing the HOME button, the current activity is stopped and
+ <li>When the user leaves a task by pressing the <em>Home</em> button, the current activity is
+stopped and
its task goes into the background. The system retains the state of every activity in the task. If
the user later resumes the task by selecting the launcher icon that began the task, the task comes
to the foreground and resumes the activity at the top of the stack.</li>
- <li>If the user presses the BACK button, the current activity is popped from the stack and
+ <li>If the user presses the <em>Back</em> button, the current activity is popped from the stack
+and
destroyed. The previous activity in the stack is resumed. When an activity is destroyed, the system
<em>does not</em> retain the activity's state.</li>
<li>Activities can be instantiated multiple times, even from other tasks.</li>
@@ -256,7 +266,8 @@
<p class="caution"><strong>Caution:</strong> Most applications should not interrupt the default
behavior for activities and tasks. If you determine that it's necessary for your activity to modify
the default behaviors, use caution and be sure to test the usability of the activity during
-launch and when navigating back to it from other activities and tasks with the BACK button. Be sure
+launch and when navigating back to it from other activities and tasks with the <em>Back</em> button.
+Be sure
to test for navigation behaviors that might conflict with the user's expected behavior.</p>
@@ -320,8 +331,10 @@
stack remains A-B-C-D. However, if an intent arrives for an activity of type B, then a new
instance of B is added to the stack, even if its launch mode is {@code "singleTop"}.</p>
<p class="note"><strong>Note:</strong> When a new instance of an activity is created,
-the user can press the BACK button to return to the previous activity. But when an existing instance of
-an activity handles a new intent, the user cannot press the BACK button to return to the state of
+the user can press the <em>Back</em> button to return to the previous activity. But when an existing
+instance of
+an activity handles a new intent, the user cannot press the <em>Back</em> button to return to the
+state of
the activity before the new intent arrived in {@link android.app.Activity#onNewIntent
onNewIntent()}.</p>
</dd>
@@ -333,7 +346,7 @@
android.app.Activity#onNewIntent onNewIntent()} method, rather than creating a new instance. Only
one instance of the activity can exist at a time.
<p class="note"><strong>Note:</strong> Although the activity starts in a new task, the
-BACK button still returns the user to the previous activity.</p></dd>
+<em>Back</em> button still returns the user to the previous activity.</p></dd>
<dt>{@code "singleInstance"}.</dt>
<dd>Same as {@code "singleTask"}, except that the system doesn't launch any other activities into
the task holding the instance. The activity is always the single and only member of its task;
@@ -351,7 +364,7 @@
intent.</p>
<p>Regardless of whether an activity starts in a new task or in the same task as the activity that
-started it, the BACK button always takes the user to the previous activity. However, if you
+started it, the <em>Back</em> button always takes the user to the previous activity. However, if you
start an activity that specifies the {@code singleTask} launch mode, then if an instance of
that activity exists in a background task, that whole task is brought to the foreground. At this
point, the back stack now includes all activities from the task brought forward, at the top of the
@@ -454,7 +467,8 @@
However, it doesn't have to be. If there's already an existing task with the same affinity as the
new activity, the activity is launched into that task. If not, it begins a new task.</p>
-<p>If this flag causes an activity to begin a new task and the user presses the HOME button to leave
+<p>If this flag causes an activity to begin a new task and the user presses the <em>Home</em> button
+to leave
it, there must be some way for the user to navigate back to the task. Some entities (such as the
notification manager) always start activities in an external task, never as part of their own, so
they always put {@code FLAG_ACTIVITY_NEW_TASK} in the intents they pass to {@link
@@ -556,7 +570,8 @@
and a {@link android.content.Intent#CATEGORY_LAUNCHER}
filter. Imagine, for example, what could happen if the filter is missing: An intent launches a
{@code "singleTask"} activity, initiating a new task, and the user spends some time working in
-that task. The user then presses the HOME button. The task is now sent to the background and is
+that task. The user then presses the <em>Home</em> button. The task is now sent to the background
+and is
not visible. Now the user has no way to return to the task, because it is not represented in the
application launcher.
</p>
diff --git a/docs/html/guide/topics/intents/intents-filters.jd b/docs/html/guide/topics/intents/intents-filters.jd
index 3f94553..3ad3c93 100644
--- a/docs/html/guide/topics/intents/intents-filters.jd
+++ b/docs/html/guide/topics/intents/intents-filters.jd
@@ -247,7 +247,7 @@
</tr><tr>
<td>{@code CATEGORY_HOME}
<td>The activity displays the home screen, the first screen the user sees when
- the device is turned on or when the HOME key is pressed.
+ the device is turned on or when the <em>Home</em> button is pressed.
</tr><tr>
<td>{@code CATEGORY_LAUNCHER}
<td>The activity can be the initial activity of a task and is listed in
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index e76a6be..4d9603f 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -133,21 +133,21 @@
it's ignored for all other activities in the task.
<p>
-When the value is "{@code true}", every time users start the task again, they
-are brought to its root activity, regardless of what they were last doing in
-the task and regardless of whether they used BACK or HOME to last leave it.
-When the value is "{@code false}", the task may be cleared of activities in
+When the value is "{@code true}", every time users start the task again, they
+are brought to its root activity regardless of what they were last doing in
+the task and regardless of whether they used the <em>Back</em> or <em>Home</em> button to
+leave it. When the value is "{@code false}", the task may be cleared of activities in
some situations (see the
<code><a href="#always">alwaysRetainTaskState</a></code> attribute), but not always.
</p>
<p>
Suppose, for example, that someone launches activity P from the home screen,
-and from there goes to activity Q. The user next presses HOME, and then returns
+and from there goes to activity Q. The user next presses <em>Home</em>, and then returns
to activity P. Normally, the user would see activity Q, since that is what they
were last doing in P's task. However, if P set this flag to "{@code true}", all
of the activities on top of it (Q in this case) were removed when the user pressed
-HOME and the task went to the background. So the user sees only P when returning
+<em>Home</em> and the task went to the background. So the user sees only P when returning
to the task.
</p>
@@ -501,7 +501,7 @@
<p>Regardless of the launch mode that you choose, make sure to test the usability
of the activity during launch and when navigating back to it from
-other activities and tasks using the BACK key. </p>
+other activities and tasks using the <em>Back</em> button. </p>
<p>For more information on launch modes and their interaction with Intent
flags, see the
diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd
index e06563d..8b8e75b 100644
--- a/docs/html/guide/topics/search/search-dialog.jd
+++ b/docs/html/guide/topics/search/search-dialog.jd
@@ -544,7 +544,8 @@
}
</pre>
-<p>If the user cancels search by pressing the BACK button, the search dialog closes and the activity
+<p>If the user cancels search by pressing the <em>Back</em> button, the search dialog closes and the
+activity
regains input focus. You can register to be notified when the search dialog is
closed with {@link android.app.SearchManager#setOnDismissListener(SearchManager.OnDismissListener)
setOnDismissListener()}
@@ -569,7 +570,8 @@
android.content.Intent#ACTION_SEARCH} intent with a call to {@link
android.app.Activity#onCreate(Bundle) onCreate()} and a new instance of the
activity is brought to the top of the activity stack. There are now two instances of your
-searchable activity in the activity stack (so pressing the BACK button goes back to the previous
+searchable activity in the activity stack (so pressing the <em>Back</em> button goes back to the
+previous
instance of the searchable activity, rather than exiting the searchable activity).</li>
<li>If you set {@code android:launchMode} to <code>"singleTop"</code>, then the
searchable activity receives the {@link android.content.Intent#ACTION_SEARCH} intent with a call
diff --git a/docs/html/guide/topics/ui/index.jd b/docs/html/guide/topics/ui/index.jd
index d3060c5..83c8150 100644
--- a/docs/html/guide/topics/ui/index.jd
+++ b/docs/html/guide/topics/ui/index.jd
@@ -174,7 +174,8 @@
<p>Application menus are another important part of an application's UI. Menus offers a reliable interface that reveals
application functions and settings. The most common application menu is revealed by pressing
-the MENU key on the device. However, you can also add Context Menus, which may be revealed when the user presses
+the <em>Menu</em> button on the device. However, you can also add Context Menus, which may be
+revealed when the user presses
and holds down on an item.</p>
<p>Menus are also structured using a View hierarchy, but you don't define this structure yourself. Instead,
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index bef9671..d104b4b 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -173,7 +173,7 @@
</li>
<li>
The user has seen enough to know they have a meeting coming up,
- so they press the BACK button. They are now returned to Email, which
+ so they press the <em>Back</em> button. They are now returned to Email, which
is where they were when they took the notification.
</li>
</ol>
@@ -198,8 +198,8 @@
(writing an e-mail), but that message is still saved in their drafts.
</li>
<li>
- The user presses BACK once to go to the message list (the typical flow in the
- Email app), and press BACK again to return to Calendar as they left it.
+ The user presses <em>Back</em> once to go to the message list (the typical flow in the
+ Email app), and press <em>Back</em> again to return to Calendar as they left it.
</li>
</ol>
@@ -216,7 +216,7 @@
most interest is the <code>makeMessageIntentStack()</code> method, which constructs
an array of intents representing the app's new activity stack for this state.
(If you are using fragments, you may need to initialize your fragment and
-app state so that pressing BACK will switch the UI back to its parent state.)
+app state so that pressing <em>Back</em> will switch the UI back to its parent state.)
The core of this is the {@link android.content.Intent#makeRestartActivityTask
Intent.makeRestartActivityTask()} method, which constructs the root activity
of the stack with the appropriate flags, such as
diff --git a/docs/html/guide/webapps/webview.jd b/docs/html/guide/webapps/webview.jd
index ed28f21..66b5501 100644
--- a/docs/html/guide/webapps/webview.jd
+++ b/docs/html/guide/webapps/webview.jd
@@ -298,18 +298,18 @@
pages. You can navigate backward and forward through the history with {@link
android.webkit.WebView#goBack()} and {@link android.webkit.WebView#goForward()}.</p>
-<p>For example, here's how your {@link android.app.Activity} can use the device BACK key to navigate
-backward:</p>
+<p>For example, here's how your {@link android.app.Activity} can use the device <em>Back</em> button
+to navigate backward:</p>
<pre>
@Override
public boolean {@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown}(int keyCode, KeyEvent event) {
- // Check if the key event was the BACK key and if there's history
+ // Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.{@link android.webkit.WebView#canGoBack() canGoBack}() {
myWebView.{@link android.webkit.WebView#goBack() goBack}();
return true;
}
- // If it wasn't the BACK key or there's no web page history, bubble up to the default
+ // If it wasn't the Back key or there's no web page history, bubble up to the default
// system behavior (probably exit the activity)
return super.onKeyDown(keyCode, event);
}
diff --git a/docs/html/training/design-navigation/ancestral-temporal.jd b/docs/html/training/design-navigation/ancestral-temporal.jd
index c0b1aef..ab6a64d 100644
--- a/docs/html/training/design-navigation/ancestral-temporal.jd
+++ b/docs/html/training/design-navigation/ancestral-temporal.jd
@@ -29,7 +29,10 @@
</div>
-<p>Now that users can navigate <a href="descendant-lateral.html">deep into</a> the application's screen hierarchy, we need to provide a method for navigating up the hierarchy, to parent and ancestor screens. Additionally, we should ensure that temporal navigation via the BACK button is respected to respect Android conventions.</p>
+<p>Now that users can navigate <a href="descendant-lateral.html">deep into</a> the application's
+screen hierarchy, we need to provide a method for navigating up the hierarchy, to parent and
+ancestor screens. Additionally, we should ensure that temporal navigation via the <em>Back</em>
+button is respected to respect Android conventions.</p>
<div class="design-announce">
<p><strong>Back/Up Navigation Design</strong></p>
@@ -39,27 +42,52 @@
<h2 id="temporal-navigation">Support Temporal Navigation: <em>Back</em></h2>
-<p>Temporal navigation, or navigation between historical screens, is deeply rooted in the Android system. All Android users expect the BACK button to take them to the previous screen, regardless of other state. The set of historical screens is always rooted at the user's Launcher application (the phone's "home" screen). That is, pressing BACK enough times should land you back at the Launcher, after which the BACK button will do nothing.</p>
+<p>Temporal navigation, or navigation between historical screens, is deeply rooted in the Android
+system. All Android users expect the <em>Back</em> button to take them to the previous screen,
+regardless of other state. The set of historical screens is always rooted at the user's Launcher
+application (the phone's "home" screen). That is, pressing <em>Back</em> enough times should land
+you back at the Launcher, after which the <em>Back</em> button will do nothing.</p>
<img src="{@docRoot}images/training/app-navigation-ancestral-navigate-back.png"
- alt="The BACK button behavior after entering the Email app from the People (or Contacts) app" id="figure-navigate-back">
+ alt="The Back button behavior after entering the Email app from the People (or Contacts) app"
+id="figure-navigate-back">
-<p class="img-caption"><strong>Figure 1.</strong> The BACK button behavior after entering the Email app from the People (or Contacts) app.</p>
+<p class="img-caption"><strong>Figure 1.</strong> The <em>Back</em> button behavior after entering
+the Email app from the People (or Contacts) app.</p>
-<p>Applications generally don't have to worry about managing the BACK button themselves; the system handles <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">tasks and the <em>back stack</em></a>, or the list of previous screens, automatically. The BACK button by default simply traverses this list of screens, removing the current screen from the list upon being pressed.</p>
+<p>Applications generally don't have to worry about managing the <em>Back</em> button themselves;
+the system handles <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">tasks and
+the <em>back stack</em></a>, or the list of previous screens, automatically. The <em>Back</em>
+button by default simply traverses this list of screens, removing the current screen from the list
+upon being pressed.</p>
-<p>There are, however, cases where you may want to override the behavior for BACK. For example, if your screen contains an embedded web browser where users can interact with page elements to navigate between web pages, you may wish to trigger the embedded browser's default <em>back</em> behavior when users press the device's BACK button. Upon reaching the beginning of the browser's internal history, you should always defer to the system's default behavior for the BACK button.</p>
+<p>There are, however, cases where you may want to override the behavior for <em>Back</em>. For
+example, if your screen contains an embedded web browser where users can interact with page elements
+to navigate between web pages, you may wish to trigger the embedded browser's default <em>back</em>
+behavior when users press the device's <em>Back</em> button. Upon reaching the beginning of the
+browser's internal history, you should always defer to the system's default behavior for the
+<em>Back</em> button.</p>
<h2 id="ancestral-navigation">Provide Ancestral Navigation: <em>Up</em> and <em>Home</em></h2>
-<p>Before Android 3.0, the most common form of ancestral navigation was the <em>Home</em> metaphor. This was generally implemented as a <em>Home</em> item accessible via the device's MENU button, or a <em>Home</em> button at the top-left of the screen, usually as a component of the Action Bar (<a href="{@docRoot}design/patterns/actionbar.html">pattern docs</a> at Android Design). Upon selecting <em>Home</em>, the user would be taken to the screen at the top of the screen hierarchy, generally known as the application's home screen.</p>
+<p>Before Android 3.0, the most common form of ancestral navigation was the <em>Home</em> metaphor.
+This was generally implemented as a <em>Home</em> item accessible via the device's <em>Menu</em>
+button, or a <em>Home</em> button at the top-left of the screen, usually as a component of the
+Action Bar (<a href="{@docRoot}design/patterns/actionbar.html">pattern docs</a> at Android Design).
+Upon selecting <em>Home</em>, the user would be taken to the screen at the top of the screen
+hierarchy, generally known as the application's home screen.</p>
<p>Providing direct access to the application's home screen can give the user a sense of comfort and security. Regardless of where they are in the application, if they get lost in the app, they can select <em>Home</em> to arrive back at the familiar home screen.</p>
-<p>Android 3.0 introduced the <em>Up</em> metaphor, which is presented in the Action Bar as a substitute for the <em>Home</em> button described above. Upon tapping <em>Up</em>, the user should be taken to the parent screen in the hierarchy. This navigation step is usually the previous screen (as described with the BACK button discussion above), but this is not universally the case. Thus, developers must ensure that <em>Up</em> for each screen navigates to a single, predetermined parent screen.</p>
+<p>Android 3.0 introduced the <em>Up</em> metaphor, which is presented in the Action Bar as a
+substitute for the <em>Home</em> button described above. Upon tapping <em>Up</em>, the user should
+be taken to the parent screen in the hierarchy. This navigation step is usually the previous screen
+(as described with the <em>Back</em> button discussion above), but this is not universally the case.
+Thus, developers must ensure that <em>Up</em> for each screen navigates to a single, predetermined
+parent screen.</p>
<img src="{@docRoot}images/training/app-navigation-ancestral-navigate-up.png"
@@ -70,6 +98,12 @@
<p>In some cases, it's appropriate for <em>Up</em> to perform an action rather than navigating to a parent screen. Take for example, the Gmail application for Android 3.0-based tablets. When viewing a mail conversation while holding the device in landscape, the conversation list, as well as the conversation details are presented side-by-side. This is a form of parent-child screen grouping, as discussed in a <a href="multiple-sizes.html">previous lesson</a>. However, when viewing a mail conversation in the portrait orientation, only the conversation details are shown. The <em>Up</em> button is used to temporarily show the parent pane, which slides in from the left of the screen. Pressing the <em>Up</em> button again while the left pane is visible exits the context of the individual conversation, up to a full-screen list of conversations.</p>
-<p class="note"><strong>Implementation Note:</strong> As a best practice, when implementing either <em>Home</em> or <em>Up</em>, make sure to clear the back stack of any descendent screens. For <em>Home</em>, the only remaining screen on the back stack should be the home screen. For <em>Up</em> navigation, the current screen should be removed from the back stack, unless BACK navigates across screen hierarchies. You can use the {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} and {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} intent flags together to achieve this.</p>
+<p class="note"><strong>Implementation Note:</strong> As a best practice, when implementing either
+<em>Home</em> or <em>Up</em>, make sure to clear the back stack of any descendent screens. For
+<em>Home</em>, the only remaining screen on the back stack should be the home screen. For
+<em>Up</em> navigation, the current screen should be removed from the back stack, unless
+<em>Back</em> navigates across screen hierarchies. You can use the {@link
+android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} and {@link
+android.content.Intent#FLAG_ACTIVITY_NEW_TASK} intent flags together to achieve this.</p>
<p>In the last lesson, we apply the concepts discussed in all of the lessons so far to create interaction design wireframes for our example news application.</p>
diff --git a/docs/html/training/design-navigation/descendant-lateral.jd b/docs/html/training/design-navigation/descendant-lateral.jd
index 0064bd4..2d97e40 100644
--- a/docs/html/training/design-navigation/descendant-lateral.jd
+++ b/docs/html/training/design-navigation/descendant-lateral.jd
@@ -117,7 +117,16 @@
<p class="img-caption"><strong>Figure 5.</strong> Example phone and tablet tab-based navigation interfaces with relevant screen map excerpt.</p>
-<p>Several best practices apply when using tabs. Tabs should be persistent across immediate related screens. Only the designated content region should change when selecting a tab, and tab indicators should remain available at all times. Additionally, tab switches should not be treated as history. For example, if a user switches from a tab <em>A</em> to another tab <em>B</em>, pressing the BACK button (more on that in the <a href="ancestral-temporal.html">next lesson</a>) should not re-select tab <em>A</em>. Tabs are usually laid out horizontally, although other presentations of tab navigation such as using a drop-down list in the Action Bar (<a href="{@docRoot}design/patterns/actionbar.html">pattern docs</a> at Android Design) are sometimes appropriate. Lastly, and most importantly, <em>tabs should always run along the top of the screen</em>, and should not be aligned to the bottom of the screen.</p>
+<p>Several best practices apply when using tabs. Tabs should be persistent across immediate related
+screens. Only the designated content region should change when selecting a tab, and tab indicators
+should remain available at all times. Additionally, tab switches should not be treated as history.
+For example, if a user switches from a tab <em>A</em> to another tab <em>B</em>, pressing the
+<em>Back</em> button (more on that in the <a href="ancestral-temporal.html">next lesson</a>) should
+not re-select tab <em>A</em>. Tabs are usually laid out horizontally, although other presentations
+of tab navigation such as using a drop-down list in the Action Bar (<a
+href="{@docRoot}design/patterns/actionbar.html">pattern docs</a> at Android Design) are sometimes
+appropriate. Lastly, and most importantly, <em>tabs should always run along the top of the
+screen</em>, and should not be aligned to the bottom of the screen.</p>
<p>There are some obvious immediate benefits of tabs over simpler list- and button-based navigation:</p>
diff --git a/docs/html/training/design-navigation/index.jd b/docs/html/training/design-navigation/index.jd
index cb20a60..af60717 100644
--- a/docs/html/training/design-navigation/index.jd
+++ b/docs/html/training/design-navigation/index.jd
@@ -41,7 +41,9 @@
<dd>Learn about techniques for allowing users to navigate deep into, as well as across, your content hierarchy. Also learn about pros and cons of, and best practices for, specific navigational UI elements for various situations.</dd>
<dt><strong><a href="ancestral-temporal.html">Providing Ancestral and Temporal Navigation</a></strong></dt>
- <dd>Learn how to allow users to navigate upwards in the content hierarchy. Also learn about best practices for the BACK button and temporal navigation, or navigation to previous screens that may not be hierarchically related.</dd>
+ <dd>Learn how to allow users to navigate upwards in the content hierarchy. Also learn about best
+practices for the <em>Back</em> button and temporal navigation, or navigation to previous screens
+that may not be hierarchically related.</dd>
<dt><strong><a href="wireframing.html">Putting it All Together: Wireframing the Example App</a></strong></dt>
<dd>Learn how to create screen wireframes (low-fidelity graphic mockups) representing the screens in a news application based on the desired information model. These wireframes utilize navigational elements discussed in previous lessons to demonstrate intuitive and efficient navigation.</dd>
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 03ad5ae..bfe412c 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2008-2012 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.
@@ -837,7 +837,8 @@
mRS.mErrorCallback.mErrorNum = subID;
mRS.mErrorCallback.run();
} else {
- throw new RSRuntimeException("Received error num " + subID + ", details: " + e);
+ // Do not throw here. In these cases, we do not have
+ // a fatal error.
}
continue;
}
diff --git a/include/media/stagefright/AACWriter.h b/include/media/stagefright/AACWriter.h
index fa3ab8a..49397ee 100644
--- a/include/media/stagefright/AACWriter.h
+++ b/include/media/stagefright/AACWriter.h
@@ -34,7 +34,7 @@
virtual status_t addSource(const sp<MediaSource> &source);
virtual bool reachedEOS();
virtual status_t start(MetaData *params = NULL);
- virtual status_t stop();
+ virtual status_t stop() { return reset(); }
virtual status_t pause();
protected:
@@ -66,6 +66,7 @@
bool exceedsFileSizeLimit();
bool exceedsFileDurationLimit();
status_t writeAdtsHeader(uint32_t frameLength);
+ status_t reset();
DISALLOW_EVIL_CONSTRUCTORS(AACWriter);
};
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h
index 62d57b4..392f968 100644
--- a/include/media/stagefright/AMRWriter.h
+++ b/include/media/stagefright/AMRWriter.h
@@ -37,7 +37,7 @@
virtual status_t addSource(const sp<MediaSource> &source);
virtual bool reachedEOS();
virtual status_t start(MetaData *params = NULL);
- virtual status_t stop();
+ virtual status_t stop() { return reset(); }
virtual status_t pause();
protected:
@@ -60,6 +60,7 @@
status_t threadFunc();
bool exceedsFileSizeLimit();
bool exceedsFileDurationLimit();
+ status_t reset();
AMRWriter(const AMRWriter &);
AMRWriter &operator=(const AMRWriter &);
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index 2427e2f..79437bf 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -40,7 +40,7 @@
status_t initCheck() const;
virtual status_t start(MetaData *params = NULL);
- virtual status_t stop();
+ virtual status_t stop() { return reset(); }
virtual sp<MetaData> getFormat();
// Returns the maximum amplitude since last call.
@@ -97,6 +97,7 @@
void releaseQueuedFrames_l();
void waitOutstandingEncodingFrames_l();
+ status_t reset();
AudioSource(const AudioSource &);
AudioSource &operator=(const AudioSource &);
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 446720b..5a35358 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -79,7 +79,7 @@
virtual ~CameraSource();
virtual status_t start(MetaData *params = NULL);
- virtual status_t stop();
+ virtual status_t stop() { return reset(); }
virtual status_t read(
MediaBuffer **buffer, const ReadOptions *options = NULL);
@@ -163,7 +163,6 @@
bool storeMetaDataInVideoBuffers);
virtual void startCameraRecording();
- virtual void stopCameraRecording();
virtual void releaseRecordingFrame(const sp<IMemory>& frame);
// Returns true if need to skip the current frame.
@@ -220,7 +219,9 @@
status_t checkFrameRate(const CameraParameters& params,
int32_t frameRate);
+ void stopCameraRecording();
void releaseCamera();
+ status_t reset();
CameraSource(const CameraSource &);
CameraSource &operator=(const CameraSource &);
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index b060691..0936da2 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -121,9 +121,6 @@
// Wrapper over CameraSource::read() to implement quick stop.
virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
- // For video camera case, just stops the camera's video recording.
- virtual void stopCameraRecording();
-
// mSkipCurrentFrame is set to true in dataCallbackTimestamp() if the current
// frame needs to be skipped and this function just returns the value of mSkipCurrentFrame.
virtual bool skipCurrentFrame(int64_t timestampUs);
diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h
index e4c1c49..a7c9ecf 100644
--- a/include/media/stagefright/MPEG2TSWriter.h
+++ b/include/media/stagefright/MPEG2TSWriter.h
@@ -37,7 +37,7 @@
virtual status_t addSource(const sp<MediaSource> &source);
virtual status_t start(MetaData *param = NULL);
- virtual status_t stop();
+ virtual status_t stop() { return reset(); }
virtual status_t pause();
virtual bool reachedEOS();
virtual status_t dump(int fd, const Vector<String16>& args);
@@ -78,6 +78,7 @@
void writeAccessUnit(int32_t sourceIndex, const sp<ABuffer> &buffer);
ssize_t internalWrite(const void *data, size_t size);
+ status_t reset();
DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSWriter);
};
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 77166ed..0409b30 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -37,7 +37,7 @@
virtual status_t addSource(const sp<MediaSource> &source);
virtual status_t start(MetaData *param = NULL);
- virtual status_t stop();
+ virtual status_t stop() { return reset(); }
virtual status_t pause();
virtual bool reachedEOS();
virtual status_t dump(int fd, const Vector<String16>& args);
@@ -184,6 +184,7 @@
void writeLongitude(int degreex10000);
void sendSessionSummary();
void release();
+ status_t reset();
MPEG4Writer(const MPEG4Writer &);
MPEG4Writer &operator=(const MPEG4Writer &);
diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp
index 1673ccd..9cdb463 100644
--- a/media/libstagefright/AACWriter.cpp
+++ b/media/libstagefright/AACWriter.cpp
@@ -60,7 +60,7 @@
AACWriter::~AACWriter() {
if (mStarted) {
- stop();
+ reset();
}
if (mFd != -1) {
@@ -152,7 +152,7 @@
return OK;
}
-status_t AACWriter::stop() {
+status_t AACWriter::reset() {
if (!mStarted) {
return OK;
}
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 6c4e307..59b4ca7 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -52,7 +52,7 @@
AMRWriter::~AMRWriter() {
if (mStarted) {
- stop();
+ reset();
}
if (mFd != -1) {
@@ -152,7 +152,7 @@
return OK;
}
-status_t AMRWriter::stop() {
+status_t AMRWriter::reset() {
if (!mStarted) {
return OK;
}
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 8bdb7c5..fef2a00 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -72,7 +72,7 @@
AudioSource::~AudioSource() {
if (mStarted) {
- stop();
+ reset();
}
delete mRecord;
@@ -130,7 +130,7 @@
}
}
-status_t AudioSource::stop() {
+status_t AudioSource::reset() {
Mutex::Autolock autoLock(mLock);
if (!mStarted) {
return UNKNOWN_ERROR;
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 1850c9c..228659c 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -548,7 +548,7 @@
CameraSource::~CameraSource() {
if (mStarted) {
- stop();
+ reset();
} else if (mInitCheck == OK) {
// Camera is initialized but because start() is never called,
// the lock on Camera is never released(). This makes sure
@@ -632,8 +632,8 @@
mCameraFlags = 0;
}
-status_t CameraSource::stop() {
- ALOGD("stop: E");
+status_t CameraSource::reset() {
+ ALOGD("reset: E");
Mutex::Autolock autoLock(mLock);
mStarted = false;
mFrameAvailableCondition.signal();
@@ -670,7 +670,7 @@
}
CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
- ALOGD("stop: X");
+ ALOGD("reset: X");
return OK;
}
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 263ab50..83d67b9 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -87,6 +87,10 @@
}
CameraSourceTimeLapse::~CameraSourceTimeLapse() {
+ if (mLastReadBufferCopy) {
+ mLastReadBufferCopy->release();
+ mLastReadBufferCopy = NULL;
+ }
}
void CameraSourceTimeLapse::startQuickReadReturns() {
@@ -204,15 +208,6 @@
}
}
-void CameraSourceTimeLapse::stopCameraRecording() {
- ALOGV("stopCameraRecording");
- CameraSource::stopCameraRecording();
- if (mLastReadBufferCopy) {
- mLastReadBufferCopy->release();
- mLastReadBufferCopy = NULL;
- }
-}
-
sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(
const sp<IMemory> &source_data) {
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 36009ab..0b4ecbe 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -513,7 +513,7 @@
MPEG2TSWriter::~MPEG2TSWriter() {
if (mStarted) {
- stop();
+ reset();
}
mLooper->unregisterHandler(mReflector->id());
@@ -564,7 +564,7 @@
return OK;
}
-status_t MPEG2TSWriter::stop() {
+status_t MPEG2TSWriter::reset() {
CHECK(mStarted);
for (size_t i = 0; i < mSources.size(); ++i) {
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 06dd875..068660b 100755
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -282,7 +282,7 @@
}
MPEG4Writer::~MPEG4Writer() {
- stop();
+ reset();
while (!mTracks.empty()) {
List<Track *>::iterator it = mTracks.begin();
@@ -616,7 +616,7 @@
mStarted = false;
}
-status_t MPEG4Writer::stop() {
+status_t MPEG4Writer::reset() {
if (mInitCheck != OK) {
return OK;
} else {
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 5cf5236..6b2ae51 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -345,42 +345,73 @@
void egl_display_t::loseCurrent(egl_context_t * cur_c)
{
if (cur_c) {
- egl_surface_t * cur_r = get_surface(cur_c->read);
- egl_surface_t * cur_d = get_surface(cur_c->draw);
+ egl_display_t* display = cur_c->getDisplay();
+ if (display) {
+ display->loseCurrentImpl(cur_c);
+ }
+ }
+}
- // by construction, these are either 0 or valid (possibly terminated)
- // it should be impossible for these to be invalid
- ContextRef _cur_c(cur_c);
- SurfaceRef _cur_r(cur_r);
- SurfaceRef _cur_d(cur_d);
+void egl_display_t::loseCurrentImpl(egl_context_t * cur_c)
+{
+ // by construction, these are either 0 or valid (possibly terminated)
+ // it should be impossible for these to be invalid
+ ContextRef _cur_c(cur_c);
+ SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL);
+ SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
+ { // scope for the lock
+ Mutex::Autolock _l(lock);
cur_c->onLooseCurrent();
- _cur_c.release();
- _cur_r.release();
- _cur_d.release();
}
+
+ // This cannot be called with the lock held because it might end-up
+ // calling back into EGL (in particular when a surface is destroyed
+ // it calls ANativeWindow::disconnect
+ _cur_c.release();
+ _cur_r.release();
+ _cur_d.release();
}
EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c,
EGLSurface draw, EGLSurface read, EGLContext ctx,
EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx)
{
- Mutex::Autolock _l(lock);
EGLBoolean result;
- if (c) {
- result = c->cnx->egl.eglMakeCurrent(
- disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
- } else {
- result = cur_c->cnx->egl.eglMakeCurrent(
- disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
- }
- if (result == EGL_TRUE) {
- loseCurrent(cur_c);
+
+ // by construction, these are either 0 or valid (possibly terminated)
+ // it should be impossible for these to be invalid
+ ContextRef _cur_c(cur_c);
+ SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL);
+ SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
+
+ { // scope for the lock
+ Mutex::Autolock _l(lock);
if (c) {
- c->onMakeCurrent(draw, read);
+ result = c->cnx->egl.eglMakeCurrent(
+ disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
+ if (result == EGL_TRUE) {
+ c->onMakeCurrent(draw, read);
+ }
+ } else {
+ result = cur_c->cnx->egl.eglMakeCurrent(
+ disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
+ if (result == EGL_TRUE) {
+ cur_c->onLooseCurrent();
+ }
}
}
+
+ if (result == EGL_TRUE) {
+ // This cannot be called with the lock held because it might end-up
+ // calling back into EGL (in particular when a surface is destroyed
+ // it calls ANativeWindow::disconnect
+ _cur_c.release();
+ _cur_r.release();
+ _cur_d.release();
+ }
+
return result;
}
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 4479e00..f3c4ddf 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -64,6 +64,7 @@
class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes
static egl_display_t sDisplay[NUM_DISPLAYS];
EGLDisplay getDisplay(EGLNativeDisplayType display);
+ void loseCurrentImpl(egl_context_t * cur_c);
public:
enum {
diff --git a/packages/SystemUI/lint.xml b/packages/SystemUI/lint.xml
new file mode 100644
index 0000000..59a7109
--- /dev/null
+++ b/packages/SystemUI/lint.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+ <issue id="PrivateResource" severity="ignore" />
+</lint>
\ No newline at end of file
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 5c9396f..9772d6a 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -48,6 +48,7 @@
import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.net.TrafficStats.MB_IN_BYTES;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
@@ -156,10 +157,6 @@
private static final int VERSION_ADDED_METERED = 4;
private static final int VERSION_SPLIT_SNOOZE = 5;
- private static final long KB_IN_BYTES = 1024;
- private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
- private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
-
// @VisibleForTesting
public static final int TYPE_WARNING = 0x1;
public static final int TYPE_LIMIT = 0x2;
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 414ed1e..c9b67fc 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -34,6 +34,7 @@
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi;
+import static android.net.TrafficStats.MB_IN_BYTES;
import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_DEV_DELETE_AGE;
import static android.provider.Settings.Secure.NETSTATS_DEV_PERSIST_BYTES;
@@ -153,10 +154,6 @@
private PendingIntent mPollIntent;
- private static final long KB_IN_BYTES = 1024;
- private static final long MB_IN_BYTES = 1024 * KB_IN_BYTES;
- private static final long GB_IN_BYTES = 1024 * MB_IN_BYTES;
-
private static final String PREFIX_DEV = "dev";
private static final String PREFIX_UID = "uid";
private static final String PREFIX_UID_TAG = "uid_tag";
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 8b4c074..42e280f 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -32,6 +32,7 @@
endif
ifeq ($(TARGET_BOARD_PLATFORM), omap4)
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
+ LOCAL_CFLAGS += -DUSE_TRIPLE_BUFFERING
endif
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index 09f1906..69f1aca 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -43,14 +43,6 @@
DisplayHardwareBase::DisplayEventThread::~DisplayEventThread() {
}
-void DisplayHardwareBase::DisplayEventThread::onFirstRef() {
- if (initCheck() == NO_ERROR) {
- run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
- } else {
- ALOGW("/sys/power/wait_for_fb_{wake|sleep} don't exist");
- }
-}
-
status_t DisplayHardwareBase::DisplayEventThread::initCheck() const {
return ((access(kSleepFileName, R_OK) == 0 &&
access(kWakeFileName, R_OK) == 0)) ? NO_ERROR : NO_INIT;
@@ -120,6 +112,14 @@
mDisplayEventThread = new DisplayEventThread(flinger);
}
+void DisplayHardwareBase::startSleepManagement() const {
+ if (mDisplayEventThread->initCheck() == NO_ERROR) {
+ mDisplayEventThread->run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
+ } else {
+ ALOGW("/sys/power/wait_for_fb_{wake|sleep} don't exist");
+ }
+}
+
DisplayHardwareBase::~DisplayHardwareBase() {
// request exit
mDisplayEventThread->requestExitAndWait();
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
index 91ea602..fba211b 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
@@ -35,6 +35,8 @@
~DisplayHardwareBase();
+ void startSleepManagement() const;
+
// console management
void releaseScreen() const;
void acquireScreen() const;
@@ -52,7 +54,6 @@
public:
DisplayEventThread(const sp<SurfaceFlinger>& flinger);
virtual ~DisplayEventThread();
- virtual void onFirstRef();
virtual bool threadLoop();
status_t releaseScreen() const;
status_t initCheck() const;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 64f72d5..3e6b872 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -98,7 +98,12 @@
mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
mSurfaceTexture->setSynchronousMode(true);
+#ifdef USE_TRIPLE_BUFFERING
+#warning "using triple buffering"
+ mSurfaceTexture->setBufferCountServer(3);
+#else
mSurfaceTexture->setBufferCountServer(2);
+#endif
}
Layer::~Layer()
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 44aafdf..e764001 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -458,16 +458,21 @@
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
{
const Layer::State& s(drawingState());
+
+ snprintf(buffer, SIZE,
+ "+ %s %p (%s)\n",
+ getTypeId(), this, getName().string());
+ result.append(buffer);
+
s.transparentRegion.dump(result, "transparentRegion");
transparentRegionScreen.dump(result, "transparentRegionScreen");
visibleRegionScreen.dump(result, "visibleRegionScreen");
+
snprintf(buffer, SIZE,
- "+ %s %p (%s)\n"
" "
"z=%9d, pos=(%g,%g), size=(%4d,%4d), "
"isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
- getTypeId(), this, getName().string(),
s.z, s.transform.tx(), s.transform.ty(), s.w, s.h,
isOpaque(), needsDithering(), contentDirty,
s.alpha, s.flags,
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 1ff3567..290fff4 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -133,7 +133,8 @@
}
void MessageQueue::invalidate() {
- mHandler->signalInvalidate();
+// mHandler->signalInvalidate();
+ mEvents->requestNextVsync();
}
void MessageQueue::refresh() {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 870235b..ab09bfa 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -300,6 +300,7 @@
// start the EventThread
mEventThread = new EventThread(this);
mEventQueue.setEventThread(mEventThread);
+ hw.startSleepManagement();
/*
* We're now ready to accept clients...
@@ -403,7 +404,8 @@
void SurfaceFlinger::onMessageReceived(int32_t what)
{
switch (what) {
- case MessageQueue::INVALIDATE: {
+ case MessageQueue::REFRESH: {
+// case MessageQueue::INVALIDATE: {
// check for transactions
if (CC_UNLIKELY(mConsoleSignals)) {
handleConsoleEvents();
@@ -419,42 +421,47 @@
// post surfaces (if needed)
handlePageFlip();
- if (!mDirtyRegion.isEmpty()) {
- signalRefresh();
- }
- } break;
+// signalRefresh();
+//
+// } break;
+//
+// case MessageQueue::REFRESH: {
- case MessageQueue::REFRESH: {
- if (!mDirtyRegion.isEmpty()) {
- // NOTE: it is mandatory to call hw.compositionComplete()
- // after handleRefresh()
- handleRefresh();
+ handleRefresh();
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- if (CC_UNLIKELY(mHwWorkListDirty)) {
- // build the h/w work list
- handleWorkList();
- }
- if (CC_LIKELY(hw.canDraw())) {
- // repaint the framebuffer (if needed)
- handleRepaint();
- // inform the h/w that we're done compositing
- hw.compositionComplete();
- postFramebuffer();
- } else {
- // pretend we did the post
- hw.compositionComplete();
- }
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+
+// if (mDirtyRegion.isEmpty()) {
+// return;
+// }
+
+ if (CC_UNLIKELY(mHwWorkListDirty)) {
+ // build the h/w work list
+ handleWorkList();
}
+
+ if (CC_LIKELY(hw.canDraw())) {
+ // repaint the framebuffer (if needed)
+ handleRepaint();
+ // inform the h/w that we're done compositing
+ hw.compositionComplete();
+ postFramebuffer();
+ } else {
+ // pretend we did the post
+ hw.compositionComplete();
+ }
+
} break;
}
}
void SurfaceFlinger::postFramebuffer()
{
- // this should never happen. we do the flip anyways so we don't
- // risk to cause a deadlock with hwc
- ALOGW_IF(mSwapRegion.isEmpty(), "mSwapRegion is empty");
+ // mSwapRegion can be empty here is some cases, for instance if a hidden
+ // or fully transparent window is updating.
+ // in that case, we need to flip anyways to not risk a deadlock with
+ // h/w composer.
+
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const nsecs_t now = systemTime();
mDebugInSwapBuffers = now;
@@ -1651,11 +1658,13 @@
snprintf(buffer, SIZE,
" last eglSwapBuffers() time: %f us\n"
" last transaction time : %f us\n"
+ " transaction-flags : %08x\n"
" refresh-rate : %f fps\n"
" x-dpi : %f\n"
" y-dpi : %f\n",
mLastSwapBufferTime/1000.0,
mLastTransactionTime/1000.0,
+ mTransactionFlags,
hw.getRefreshRate(),
hw.getDpiX(),
hw.getDpiY());
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 2bf8b1c..e863f8b 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -28,6 +28,8 @@
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
+import static android.net.TrafficStats.KB_IN_BYTES;
+import static android.net.TrafficStats.MB_IN_BYTES;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
@@ -100,10 +102,6 @@
private static final long TEST_START = 1194220800000L;
private static final String TEST_IFACE = "test0";
- private static final long KB_IN_BYTES = 1024;
- private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
- private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
-
private static NetworkTemplate sTemplateWifi = NetworkTemplate.buildTemplateWifi();
private BroadcastInterceptingContext mServiceContext;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 8f5e77e..daf2018 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -31,6 +31,7 @@
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi;
+import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
@@ -92,10 +93,6 @@
private static final String IMSI_1 = "310004";
private static final String IMSI_2 = "310260";
- private static final long KB_IN_BYTES = 1024;
- private static final long MB_IN_BYTES = 1024 * KB_IN_BYTES;
- private static final long GB_IN_BYTES = 1024 * MB_IN_BYTES;
-
private static NetworkTemplate sTemplateWifi = buildTemplateWifi();
private static NetworkTemplate sTemplateImsi1 = buildTemplateMobileAll(IMSI_1);
private static NetworkTemplate sTemplateImsi2 = buildTemplateMobileAll(IMSI_2);
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
index a706f78..a38ac25 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
@@ -40,8 +40,11 @@
private long mContentInvalMillis;
private static final int LOAD_STALL_MILLIS = 2000; // nr of millis after load,
// before test is forced
- private double mLoadTime;
- private double mAnimationTime;
+
+ // ignore anim end events until this many millis after load
+ private static final long ANIM_SAFETY_THRESHOLD = 200;
+ private long mLoadTime;
+ private long mAnimationTime;
public ProfiledWebView(Context context) {
super(context);
@@ -131,7 +134,6 @@
// invalidate all content, and kick off redraw
Log.d("ProfiledWebView",
"kicking off test with callback registration, and tile discard...");
- registerPageSwapCallback();
discardAllTextures();
invalidate();
mIsScrolling = true;
@@ -150,10 +152,11 @@
*/
@Override
protected void pageSwapCallback(boolean startAnim) {
+ super.pageSwapCallback(startAnim);
+
if (!mIsTesting && mIsScrolling) {
// kick off testing
mContentInvalMillis = System.currentTimeMillis() - mContentInvalMillis;
- super.pageSwapCallback(startAnim);
Log.d("ProfiledWebView", "REDRAW TOOK " + mContentInvalMillis + "millis");
mIsTesting = true;
invalidate(); // ensure a redraw so that auto-scrolling can occur
@@ -166,14 +169,14 @@
String updatesString = settings.getProperty("tree_updates");
int updates = (updatesString == null) ? -1 : Integer.parseInt(updatesString);
- double animationTime;
- if (mAnimationTime == 0) {
+ long animationTime;
+ if (mAnimationTime == 0 || mAnimationTime - mLoadTime < ANIM_SAFETY_THRESHOLD) {
animationTime = System.currentTimeMillis() - mLoadTime;
} else {
animationTime = mAnimationTime - mLoadTime;
}
- return updates * 1000 / animationTime;
+ return updates * 1000.0 / animationTime;
}
public void setDoubleBuffering(boolean useDoubleBuffering) {
diff --git a/tests/touchlag/Android.mk b/tests/touchlag/Android.mk
new file mode 100644
index 0000000..4f8aa1e
--- /dev/null
+++ b/tests/touchlag/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ touchlag.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils libutils \
+
+LOCAL_MODULE:= test-touchlag
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/tests/touchlag/touchlag.cpp b/tests/touchlag/touchlag.cpp
new file mode 100644
index 0000000..df4befb
--- /dev/null
+++ b/tests/touchlag/touchlag.cpp
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <linux/input.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <cutils/memory.h>
+#include <asm-generic/mman.h>
+#include <sys/mman.h>
+#include <utils/threads.h>
+#include <unistd.h>
+#include <math.h>
+
+using namespace android;
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#endif
+
+struct Buffer {
+ size_t w;
+ size_t h;
+ size_t s;
+ union {
+ void* addr;
+ uint32_t* pixels;
+ };
+};
+
+void clearBuffer(Buffer* buf, uint32_t pixel) {
+ android_memset32(buf->pixels, pixel, buf->s * buf->h * 4);
+}
+
+void drawTwoPixels(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) {
+ if (y>0 && y<ssize_t(buf->h)) {
+ uint32_t* bits = buf->pixels + y * buf->s;
+ if (x>=0 && x<buf->w) {
+ bits[x] = pixel;
+ }
+ ssize_t W(w);
+ if ((x+W)>=0 && (x+W)<buf->w) {
+ bits[x+W] = pixel;
+ }
+ }
+}
+
+void drawHLine(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) {
+ if (y>0 && y<ssize_t(buf->h)) {
+ ssize_t W(w);
+ if (x<0) {
+ W += x;
+ x = 0;
+ }
+ if (x+w > buf->w) {
+ W = buf->w - x;
+ }
+ if (W>0) {
+ uint32_t* bits = buf->pixels + y * buf->s + x;
+ android_memset32(bits, pixel, W*4);
+ }
+ }
+}
+
+void drawRect(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w, size_t h) {
+ ssize_t W(w), H(h);
+ if (x<0) {
+ w += x;
+ x = 0;
+ }
+ if (y<0) {
+ h += y;
+ y = 0;
+ }
+ if (x+w > buf->w) W = buf->w - x;
+ if (y+h > buf->h) H = buf->h - y;
+ if (W>0 && H>0) {
+ uint32_t* bits = buf->pixels + y * buf->s + x;
+ for (ssize_t i=0 ; i<H ; i++) {
+ android_memset32(bits, pixel, W*4);
+ bits += buf->s;
+ }
+ }
+}
+
+void drawCircle(Buffer* buf, uint32_t pixel,
+ size_t x0, size_t y0, size_t radius, bool filled = false) {
+ ssize_t f = 1 - radius;
+ ssize_t ddF_x = 1;
+ ssize_t ddF_y = -2 * radius;
+ ssize_t x = 0;
+ ssize_t y = radius;
+ if (filled) {
+ drawHLine(buf, pixel, x0-radius, y0, 2*radius);
+ } else {
+ drawTwoPixels(buf, pixel, x0-radius, y0, 2*radius);
+ }
+ while (x < y) {
+ if (f >= 0) {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+ if (filled) {
+ drawHLine(buf, pixel, x0-x, y0+y, 2*x);
+ drawHLine(buf, pixel, x0-x, y0-y, 2*x);
+ drawHLine(buf, pixel, x0-y, y0+x, 2*y);
+ drawHLine(buf, pixel, x0-y, y0-x, 2*y);
+ } else {
+ drawTwoPixels(buf, pixel, x0-x, y0+y, 2*x);
+ drawTwoPixels(buf, pixel, x0-x, y0-y, 2*x);
+ drawTwoPixels(buf, pixel, x0-y, y0+x, 2*y);
+ drawTwoPixels(buf, pixel, x0-y, y0-x, 2*y);
+ }
+ }
+}
+
+class TouchEvents {
+ class EventThread : public Thread {
+ int fd;
+
+ virtual bool threadLoop() {
+ input_event event;
+ int first_down = 0;
+ do {
+ read(fd, &event, sizeof(event));
+ if (event.type == EV_ABS) {
+ if (event.code == ABS_MT_TRACKING_ID) {
+ down = event.value == -1 ? 0 : 1;
+ first_down = down;
+ }
+ if (event.code == ABS_MT_POSITION_X) {
+ x = event.value;
+ }
+ if (event.code == ABS_MT_POSITION_Y) {
+ y = event.value;
+ }
+ }
+ } while (event.type == EV_SYN);
+ return true;
+ }
+
+ public:
+ int x, y, down;
+ EventThread() : Thread(false),
+ x(0), y(0), down(0)
+ {
+ fd = open("/dev/input/event1", O_RDONLY);
+ }
+};
+ sp<EventThread> thread;
+
+public:
+ TouchEvents() {
+ thread = new EventThread();
+ thread->run("EventThread", PRIORITY_URGENT_DISPLAY);
+ }
+
+ int getMostRecentPosition(int* x, int* y) {
+ *x = thread->x;
+ *y = thread->y;
+ return thread->down;
+ }
+};
+
+
+struct Queue {
+ struct position {
+ int x, y;
+ };
+ int index;
+ position q[16];
+ Queue() : index(0) { }
+ void push(int x, int y) {
+ index++;
+ index &= 0xF;
+ q[index].x = x;
+ q[index].y = y;
+ }
+ void get(int lag, int* x, int* y) {
+ const int i = (index - lag) & 0xF;
+ *x = q[i].x;
+ *y = q[i].y;
+ }
+};
+
+extern char *optarg;
+extern int optind;
+extern int optopt;
+extern int opterr;
+extern int optreset;
+
+void usage(const char* name) {
+ printf("\nusage: %s [-h] [-l lag]\n", name);
+}
+
+int main(int argc, char** argv) {
+ fb_var_screeninfo vi;
+ fb_fix_screeninfo fi;
+
+ int lag = 0;
+ int fd = open("/dev/graphics/fb0", O_RDWR);
+ ioctl(fd, FBIOGET_VSCREENINFO, &vi);
+ ioctl(fd, FBIOGET_FSCREENINFO, &fi);
+ void* bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ Buffer framebuffer;
+ framebuffer.w = vi.xres;
+ framebuffer.h = vi.yres;
+ framebuffer.s = fi.line_length / (vi.bits_per_pixel >> 3);
+ framebuffer.addr = bits;
+
+ int ch;
+ while ((ch = getopt(argc, argv, "hl:")) != -1) {
+ switch (ch) {
+ case 'l':
+ lag = atoi(optarg);
+ break;
+ case 'h':
+ default:
+ usage(argv[0]);
+ exit(0);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+
+ TouchEvents touch;
+ Queue queue;
+
+
+ int x=0, y=0, down=0;
+ int lag_x=0, lag_y=0;
+
+ clearBuffer(&framebuffer, 0);
+ while (true) {
+ uint32_t crt = 0;
+ int err = ioctl(fd, FBIO_WAITFORVSYNC, &crt);
+
+ // draw beam marker
+ drawRect(&framebuffer, 0x400000, framebuffer.w-2, 0, 2, framebuffer.h);
+ // erase screen
+ if (lag) {
+ drawCircle(&framebuffer, 0, lag_x, lag_y, 100);
+ drawHLine(&framebuffer, 0, 0, lag_y, 32);
+ }
+ drawCircle(&framebuffer, 0, x, y, 100, true);
+ drawHLine(&framebuffer, 0, 0, y, 32);
+
+ // draw a line at y=1000
+ drawHLine(&framebuffer, 0x808080, 0, 1000, framebuffer.w);
+
+ // get touch events
+ touch.getMostRecentPosition(&x, &y);
+ queue.push(x, y);
+ queue.get(lag, &lag_x, &lag_y);
+
+ if (lag) {
+ drawCircle(&framebuffer, 0x00FF00, lag_x, lag_y, 100);
+ drawHLine(&framebuffer, 0x00FF00, 0, lag_y, 32);
+ }
+
+ drawCircle(&framebuffer, 0xFFFFFF, x, y, 100, true);
+ drawHLine(&framebuffer, 0xFFFFFF, 0, y, 32);
+
+ // draw end of frame beam marker
+ drawRect(&framebuffer, 0x004000, framebuffer.w-2, 0, 2, framebuffer.h);
+ }
+
+ close(fd);
+ return 0;
+}
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index c0d7427..95a68d1 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -45,6 +45,7 @@
static const String16 RESOURCES_PREFIX(RESOURCES_ROOT_NAMESPACE);
static const String16 RESOURCES_PRV_PREFIX(RESOURCES_ROOT_PRV_NAMESPACE);
+static const String16 RESOURCES_TOOLS_NAMESPACE("http://schemas.android.com/tools");
String16 getNamespaceResourcePackage(String16 namespaceUri, bool* outIsPublic)
{
@@ -761,13 +762,16 @@
SourcePos(mFilename, getStartLineNumber()).error("Child to CDATA node.");
return UNKNOWN_ERROR;
}
- attribute_entry e;
- e.index = mNextAttributeIndex++;
- e.ns = ns;
- e.name = name;
- e.string = value;
- mAttributes.add(e);
- mAttributeOrder.add(e.index, mAttributes.size()-1);
+
+ if (ns != RESOURCES_TOOLS_NAMESPACE) {
+ attribute_entry e;
+ e.index = mNextAttributeIndex++;
+ e.ns = ns;
+ e.name = name;
+ e.string = value;
+ mAttributes.add(e);
+ mAttributeOrder.add(e.index, mAttributes.size()-1);
+ }
return NO_ERROR;
}
@@ -1215,11 +1219,13 @@
collect_attr_strings(dest, outResIds, true);
int i;
- if (mNamespacePrefix.size() > 0) {
- dest->add(mNamespacePrefix, true);
- }
- if (mNamespaceUri.size() > 0) {
- dest->add(mNamespaceUri, true);
+ if (RESOURCES_TOOLS_NAMESPACE != mNamespaceUri) {
+ if (mNamespacePrefix.size() > 0) {
+ dest->add(mNamespacePrefix, true);
+ }
+ if (mNamespaceUri.size() > 0) {
+ dest->add(mNamespaceUri, true);
+ }
}
if (mElementName.size() > 0) {
dest->add(mElementName, true);
@@ -1338,6 +1344,7 @@
const void* extData = NULL;
size_t extSize = 0;
ResXMLTree_attribute attr;
+ bool writeCurrentNode = true;
const size_t NA = mAttributes.size();
const size_t NC = mChildren.size();
@@ -1350,7 +1357,7 @@
const String16 style16("style");
const type type = getType();
-
+
memset(&node, 0, sizeof(node));
memset(&attr, 0, sizeof(attr));
node.header.headerSize = htods(sizeof(node));
@@ -1395,17 +1402,21 @@
}
}
} else if (type == TYPE_NAMESPACE) {
- node.header.type = htods(RES_XML_START_NAMESPACE_TYPE);
- extData = &namespaceExt;
- extSize = sizeof(namespaceExt);
- memset(&namespaceExt, 0, sizeof(namespaceExt));
- if (mNamespacePrefix.size() > 0) {
- namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix));
+ if (mNamespaceUri == RESOURCES_TOOLS_NAMESPACE) {
+ writeCurrentNode = false;
} else {
- namespaceExt.prefix.index = htodl((uint32_t)-1);
+ node.header.type = htods(RES_XML_START_NAMESPACE_TYPE);
+ extData = &namespaceExt;
+ extSize = sizeof(namespaceExt);
+ memset(&namespaceExt, 0, sizeof(namespaceExt));
+ if (mNamespacePrefix.size() > 0) {
+ namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix));
+ } else {
+ namespaceExt.prefix.index = htodl((uint32_t)-1);
+ }
+ namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix));
+ namespaceExt.uri.index = htodl(strings.offsetForString(mNamespaceUri));
}
- namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix));
- namespaceExt.uri.index = htodl(strings.offsetForString(mNamespaceUri));
LOG_ALWAYS_FATAL_IF(NA != 0, "Namespace nodes can't have attributes!");
} else if (type == TYPE_CDATA) {
node.header.type = htods(RES_XML_CDATA_TYPE);
@@ -1422,9 +1433,11 @@
node.header.size = htodl(sizeof(node) + extSize + (sizeof(attr)*NA));
- dest->writeData(&node, sizeof(node));
- if (extSize > 0) {
- dest->writeData(extData, extSize);
+ if (writeCurrentNode) {
+ dest->writeData(&node, sizeof(node));
+ if (extSize > 0) {
+ dest->writeData(extData, extSize);
+ }
}
for (i=0; i<NA; i++) {
@@ -1476,12 +1489,14 @@
dest->writeData(&node, sizeof(node));
dest->writeData(&endElementExt, sizeof(endElementExt));
} else if (type == TYPE_NAMESPACE) {
- node.header.type = htods(RES_XML_END_NAMESPACE_TYPE);
- node.lineNumber = htodl(getEndLineNumber());
- node.comment.index = htodl((uint32_t)-1);
- node.header.size = htodl(sizeof(node)+extSize);
- dest->writeData(&node, sizeof(node));
- dest->writeData(extData, extSize);
+ if (writeCurrentNode) {
+ node.header.type = htods(RES_XML_END_NAMESPACE_TYPE);
+ node.lineNumber = htodl(getEndLineNumber());
+ node.comment.index = htodl((uint32_t)-1);
+ node.header.size = htodl(sizeof(node)+extSize);
+ dest->writeData(&node, sizeof(node));
+ dest->writeData(extData, extSize);
+ }
}
return NO_ERROR;