Merge "turn off some useless messages"
diff --git a/api/current.xml b/api/current.xml
index 644a7b1..953c9f3 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -2103,7 +2103,7 @@
type="int"
transient="false"
volatile="false"
- value="16843563"
+ value="16843567"
static="true"
final="true"
deprecated="not deprecated"
@@ -2125,7 +2125,7 @@
type="int"
transient="false"
volatile="false"
- value="16843572"
+ value="16843576"
static="true"
final="true"
deprecated="not deprecated"
@@ -2136,7 +2136,7 @@
type="int"
transient="false"
volatile="false"
- value="16843571"
+ value="16843575"
static="true"
final="true"
deprecated="not deprecated"
@@ -2147,7 +2147,7 @@
type="int"
transient="false"
volatile="false"
- value="16843573"
+ value="16843577"
static="true"
final="true"
deprecated="not deprecated"
@@ -2191,7 +2191,7 @@
type="int"
transient="false"
volatile="false"
- value="16843580"
+ value="16843584"
static="true"
final="true"
deprecated="not deprecated"
@@ -2213,7 +2213,7 @@
type="int"
transient="false"
volatile="false"
- value="16843576"
+ value="16843580"
static="true"
final="true"
deprecated="not deprecated"
@@ -2235,7 +2235,7 @@
type="int"
transient="false"
volatile="false"
- value="16843574"
+ value="16843578"
static="true"
final="true"
deprecated="not deprecated"
@@ -2246,7 +2246,7 @@
type="int"
transient="false"
volatile="false"
- value="16843581"
+ value="16843585"
static="true"
final="true"
deprecated="not deprecated"
@@ -2257,7 +2257,7 @@
type="int"
transient="false"
volatile="false"
- value="16843582"
+ value="16843586"
static="true"
final="true"
deprecated="not deprecated"
@@ -2466,7 +2466,7 @@
type="int"
transient="false"
volatile="false"
- value="16843570"
+ value="16843574"
static="true"
final="true"
deprecated="not deprecated"
@@ -2807,7 +2807,7 @@
type="int"
transient="false"
volatile="false"
- value="16843589"
+ value="16843593"
static="true"
final="true"
deprecated="not deprecated"
@@ -2818,7 +2818,7 @@
type="int"
transient="false"
volatile="false"
- value="16843588"
+ value="16843592"
static="true"
final="true"
deprecated="not deprecated"
@@ -4497,6 +4497,28 @@
visibility="public"
>
</field>
+<field name="fragmentNextEnterAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843563"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentNextExitAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843564"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="fragmentOpenEnterAnimation"
type="int"
transient="false"
@@ -4519,6 +4541,28 @@
visibility="public"
>
</field>
+<field name="fragmentPrevEnterAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843565"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentPrevExitAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843566"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="freezesText"
type="int"
transient="false"
@@ -4996,7 +5040,7 @@
type="int"
transient="false"
volatile="false"
- value="16843579"
+ value="16843583"
static="true"
final="true"
deprecated="not deprecated"
@@ -5117,7 +5161,7 @@
type="int"
transient="false"
volatile="false"
- value="16843566"
+ value="16843570"
static="true"
final="true"
deprecated="not deprecated"
@@ -5128,7 +5172,7 @@
type="int"
transient="false"
volatile="false"
- value="16843564"
+ value="16843568"
static="true"
final="true"
deprecated="not deprecated"
@@ -5139,7 +5183,7 @@
type="int"
transient="false"
volatile="false"
- value="16843565"
+ value="16843569"
static="true"
final="true"
deprecated="not deprecated"
@@ -5502,7 +5546,7 @@
type="int"
transient="false"
volatile="false"
- value="16843575"
+ value="16843579"
static="true"
final="true"
deprecated="not deprecated"
@@ -6778,7 +6822,7 @@
type="int"
transient="false"
volatile="false"
- value="16843568"
+ value="16843572"
static="true"
final="true"
deprecated="not deprecated"
@@ -6822,7 +6866,7 @@
type="int"
transient="false"
volatile="false"
- value="16843590"
+ value="16843594"
static="true"
final="true"
deprecated="not deprecated"
@@ -6833,7 +6877,7 @@
type="int"
transient="false"
volatile="false"
- value="16843584"
+ value="16843588"
static="true"
final="true"
deprecated="not deprecated"
@@ -6921,7 +6965,7 @@
type="int"
transient="false"
volatile="false"
- value="16843592"
+ value="16843596"
static="true"
final="true"
deprecated="not deprecated"
@@ -7735,7 +7779,7 @@
type="int"
transient="false"
volatile="false"
- value="16843585"
+ value="16843589"
static="true"
final="true"
deprecated="not deprecated"
@@ -9044,7 +9088,7 @@
type="int"
transient="false"
volatile="false"
- value="16843569"
+ value="16843573"
static="true"
final="true"
deprecated="not deprecated"
@@ -9066,7 +9110,7 @@
type="int"
transient="false"
volatile="false"
- value="16843567"
+ value="16843571"
static="true"
final="true"
deprecated="not deprecated"
@@ -9165,7 +9209,7 @@
type="int"
transient="false"
volatile="false"
- value="16843583"
+ value="16843587"
static="true"
final="true"
deprecated="not deprecated"
@@ -9396,7 +9440,7 @@
type="int"
transient="false"
volatile="false"
- value="16843578"
+ value="16843582"
static="true"
final="true"
deprecated="not deprecated"
@@ -9781,7 +9825,7 @@
type="int"
transient="false"
volatile="false"
- value="16843586"
+ value="16843590"
static="true"
final="true"
deprecated="not deprecated"
@@ -9858,7 +9902,7 @@
type="int"
transient="false"
volatile="false"
- value="16843587"
+ value="16843591"
static="true"
final="true"
deprecated="not deprecated"
@@ -9902,7 +9946,7 @@
type="int"
transient="false"
volatile="false"
- value="16843591"
+ value="16843595"
static="true"
final="true"
deprecated="not deprecated"
@@ -10320,7 +10364,7 @@
type="int"
transient="false"
volatile="false"
- value="16843577"
+ value="16843581"
static="true"
final="true"
deprecated="not deprecated"
@@ -30872,6 +30916,17 @@
visibility="public"
>
</field>
+<field name="TRANSIT_FRAGMENT_NEXT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4099"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TRANSIT_FRAGMENT_OPEN"
type="int"
transient="false"
@@ -30883,6 +30938,17 @@
visibility="public"
>
</field>
+<field name="TRANSIT_FRAGMENT_PREV"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8196"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TRANSIT_NONE"
type="int"
transient="false"
@@ -55076,6 +55142,17 @@
visibility="public"
>
</field>
+<field name="SCREEN_ORIENTATION_FULL_SENSOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SCREEN_ORIENTATION_LANDSCAPE"
type="int"
transient="false"
@@ -55109,6 +55186,28 @@
visibility="public"
>
</field>
+<field name="SCREEN_ORIENTATION_REVERSE_LANDSCAPE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREEN_ORIENTATION_REVERSE_PORTRAIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SCREEN_ORIENTATION_SENSOR"
type="int"
transient="false"
@@ -55120,6 +55219,28 @@
visibility="public"
>
</field>
+<field name="SCREEN_ORIENTATION_SENSOR_LANDSCAPE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREEN_ORIENTATION_SENSOR_PORTRAIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SCREEN_ORIENTATION_UNSPECIFIED"
type="int"
transient="false"
@@ -143207,6 +143328,8 @@
</parameter>
<parameter name="args" type="android.os.Bundle">
</parameter>
+<parameter name="next" type="boolean">
+</parameter>
</method>
<field name="EXTRA_NO_HEADERS"
type="java.lang.String"
@@ -189909,6 +190032,16 @@
deprecated="not deprecated"
visibility="public"
>
+<parameter name="action" type="int">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="description" type="android.content.ClipDescription">
+</parameter>
+<parameter name="data" type="android.content.ClipData">
+</parameter>
</method>
<method name="obtain"
return="android.view.DragEvent"
@@ -189920,15 +190053,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="action" type="int">
-</parameter>
-<parameter name="x" type="float">
-</parameter>
-<parameter name="y" type="float">
-</parameter>
-<parameter name="description" type="android.content.ClipDescription">
-</parameter>
-<parameter name="data" type="android.content.ClipData">
+<parameter name="source" type="android.view.DragEvent">
</parameter>
</method>
<method name="recycle"
@@ -203415,6 +203540,53 @@
>
</field>
</class>
+<class name="View.DragThumbnailBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="View.DragThumbnailBuilder"
+ type="android.view.View.DragThumbnailBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</constructor>
+<method name="onDrawThumbnail"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="canvas" type="android.graphics.Canvas">
+</parameter>
+</method>
+<method name="onProvideThumbnailMetrics"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="thumbnailSize" type="android.graphics.Point">
+</parameter>
+<parameter name="thumbnailTouchPoint" type="android.graphics.Point">
+</parameter>
+</method>
+</class>
<class name="View.MeasureSpec"
extends="java.lang.Object"
abstract="false"
@@ -223734,7 +223906,7 @@
>
</method>
<method name="getInAnimation"
- return="android.view.animation.Animation"
+ return="android.animation.ObjectAnimator<?>"
abstract="false"
native="false"
synchronized="false"
@@ -223745,7 +223917,7 @@
>
</method>
<method name="getOutAnimation"
- return="android.view.animation.Animation"
+ return="android.animation.ObjectAnimator<?>"
abstract="false"
native="false"
synchronized="false"
@@ -223861,7 +224033,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="inAnimation" type="android.view.animation.Animation">
+<parameter name="inAnimation" type="android.animation.ObjectAnimator<?>">
</parameter>
</method>
<method name="setInAnimation"
@@ -223889,7 +224061,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="outAnimation" type="android.view.animation.Animation">
+<parameter name="outAnimation" type="android.animation.ObjectAnimator<?>">
</parameter>
</method>
<method name="setOutAnimation"
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index da7ba6f..37e7253 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1380,6 +1380,12 @@
case FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:
rev = FragmentTransaction.TRANSIT_FRAGMENT_OPEN;
break;
+ case FragmentTransaction.TRANSIT_FRAGMENT_NEXT:
+ rev = FragmentTransaction.TRANSIT_FRAGMENT_PREV;
+ break;
+ case FragmentTransaction.TRANSIT_FRAGMENT_PREV:
+ rev = FragmentTransaction.TRANSIT_FRAGMENT_NEXT;
+ break;
}
return rev;
@@ -1398,6 +1404,16 @@
? com.android.internal.R.styleable.FragmentAnimation_fragmentCloseEnterAnimation
: com.android.internal.R.styleable.FragmentAnimation_fragmentCloseExitAnimation;
break;
+ case FragmentTransaction.TRANSIT_FRAGMENT_NEXT:
+ animAttr = enter
+ ? com.android.internal.R.styleable.FragmentAnimation_fragmentNextEnterAnimation
+ : com.android.internal.R.styleable.FragmentAnimation_fragmentNextExitAnimation;
+ break;
+ case FragmentTransaction.TRANSIT_FRAGMENT_PREV:
+ animAttr = enter
+ ? com.android.internal.R.styleable.FragmentAnimation_fragmentPrevEnterAnimation
+ : com.android.internal.R.styleable.FragmentAnimation_fragmentPrevExitAnimation;
+ break;
}
return animAttr;
}
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 09d8d26..b00476bb 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -106,10 +106,14 @@
public final int TRANSIT_UNSET = -1;
/** No animation for transition. */
public final int TRANSIT_NONE = 0;
- /** Fragment is being added */
+ /** Fragment is being added onto the stack */
public final int TRANSIT_FRAGMENT_OPEN = 1 | TRANSIT_ENTER_MASK;
- /** Fragment is being removed */
+ /** Fragment is being removed from the stack */
public final int TRANSIT_FRAGMENT_CLOSE = 2 | TRANSIT_EXIT_MASK;
+ /** Fragment is being added in a 'next' operation*/
+ public final int TRANSIT_FRAGMENT_NEXT = 3 | TRANSIT_ENTER_MASK;
+ /** Fragment is being removed in a 'previous' operation */
+ public final int TRANSIT_FRAGMENT_PREV = 4 | TRANSIT_EXIT_MASK;
/**
* Set specific animation resources to run for the fragments that are
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index e21cb97..e688c86 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -216,10 +216,41 @@
public static final int SCREEN_ORIENTATION_SENSOR = 4;
/**
- * Constant corresponding to <code>sensor</code> in
+ * Constant corresponding to <code>nosensor</code> in
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_NOSENSOR = 5;
+
+ /**
+ * Constant corresponding to <code>sensorLandscape</code> in
+ * the {@link android.R.attr#screenOrientation} attribute.
+ */
+ public static final int SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 6;
+
+ /**
+ * Constant corresponding to <code>sensorPortrait</code> in
+ * the {@link android.R.attr#screenOrientation} attribute.
+ */
+ public static final int SCREEN_ORIENTATION_SENSOR_PORTRAIT = 7;
+
+ /**
+ * Constant corresponding to <code>reverseLandscape</code> in
+ * the {@link android.R.attr#screenOrientation} attribute.
+ */
+ public static final int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
+
+ /**
+ * Constant corresponding to <code>reversePortrait</code> in
+ * the {@link android.R.attr#screenOrientation} attribute.
+ */
+ public static final int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;
+
+ /**
+ * Constant corresponding to <code>fullSensor</code> in
+ * the {@link android.R.attr#screenOrientation} attribute.
+ */
+ public static final int SCREEN_ORIENTATION_FULL_SENSOR = 10;
+
/**
* The preferred screen orientation this activity would like to run in.
* From the {@link android.R.attr#screenOrientation} attribute, one of
@@ -229,7 +260,12 @@
* {@link #SCREEN_ORIENTATION_USER},
* {@link #SCREEN_ORIENTATION_BEHIND},
* {@link #SCREEN_ORIENTATION_SENSOR},
- * {@link #SCREEN_ORIENTATION_NOSENSOR}.
+ * {@link #SCREEN_ORIENTATION_NOSENSOR},
+ * {@link #SCREEN_ORIENTATION_SENSOR_LANDSCAPE},
+ * {@link #SCREEN_ORIENTATION_SENSOR_PORTRAIT},
+ * {@link #SCREEN_ORIENTATION_REVERSE_LANDSCAPE},
+ * {@link #SCREEN_ORIENTATION_REVERSE_PORTRAIT},
+ * {@link #SCREEN_ORIENTATION_FULL_SENSOR}.
*/
public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index a6c7d9e..a59b2f8 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -893,11 +893,15 @@
}
}
- public void switchToHeaderInner(String fragmentName, Bundle args) {
+ public void switchToHeaderInner(String fragmentName, Bundle args, boolean next) {
getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
Fragment f = Fragment.instantiate(this, fragmentName, args);
- getFragmentManager().openTransaction().replace(
- com.android.internal.R.id.prefs, f).commit();
+ FragmentTransaction transaction = getFragmentManager().openTransaction();
+ transaction.setTransition(next ?
+ FragmentTransaction.TRANSIT_FRAGMENT_NEXT :
+ FragmentTransaction.TRANSIT_FRAGMENT_PREV);
+ transaction.replace(com.android.internal.R.id.prefs, f);
+ transaction.commit();
}
/**
@@ -909,7 +913,7 @@
*/
public void switchToHeader(String fragmentName, Bundle args) {
setSelectedHeader(null);
- switchToHeaderInner(fragmentName, args);
+ switchToHeaderInner(fragmentName, args, true);
}
/**
@@ -919,7 +923,8 @@
* @param header The new header to display.
*/
public void switchToHeader(Header header) {
- switchToHeaderInner(header.fragment, header.fragmentArguments);
+ switchToHeaderInner(header.fragment, header.fragmentArguments,
+ mHeaders.indexOf(header) > mHeaders.indexOf(mCurHeader));
setSelectedHeader(header);
}
@@ -979,7 +984,10 @@
FragmentTransaction transaction = getFragmentManager().openTransaction();
startPreferenceFragment(fragment, transaction);
if (push) {
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(BACK_STACK_PREFS);
+ } else {
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_NEXT);
}
transaction.commit();
}
@@ -1001,6 +1009,7 @@
FragmentTransaction transaction = getFragmentManager().openTransaction();
startPreferenceFragment(f, transaction);
transaction.setBreadCrumbTitle(pref.getTitle());
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(BACK_STACK_PREFS);
transaction.commit();
return true;
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index 47c6d3c..93598cd 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -50,10 +50,10 @@
public static final int ACTION_DRAG_EXITED = 6;
/* hide the constructor behind package scope */
- DragEvent() {
+ private DragEvent() {
}
- public static DragEvent obtain() {
+ static DragEvent obtain() {
return DragEvent.obtain(0, 0f, 0f, null, null);
}
@@ -81,6 +81,11 @@
return ev;
}
+ public static DragEvent obtain(DragEvent source) {
+ return obtain(source.mAction, source.mX, source.mY,
+ source.mClipDescription, source.mClipData);
+ }
+
public int getAction() {
return mAction;
}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 6b9cda0..85a8c1a 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -17,8 +17,6 @@
package android.view;
-import android.content.ClipData;
-import android.content.ClipDescription;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1dfd2bf..2afbe81 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -66,6 +66,7 @@
import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;
+import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -615,7 +616,6 @@
*/
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
private static final boolean DBG = false;
- static final boolean DEBUG_DRAG = true;
/**
* The logging tag used by this class with android.util.Log.
@@ -3957,6 +3957,12 @@
return true;
}
+ /** Gets the ViewRoot, or null if not attached. */
+ /*package*/ ViewRoot getViewRoot() {
+ View root = getRootView();
+ return root != null ? (ViewRoot)root.getParent() : null;
+ }
+
/**
* Call this to try to give focus to a specific view or to one of its descendants. This is a
* special variant of {@link #requestFocus() } that will allow views that are not focuable in
@@ -3970,12 +3976,9 @@
public final boolean requestFocusFromTouch() {
// Leave touch mode if we need to
if (isInTouchMode()) {
- View root = getRootView();
- if (root != null) {
- ViewRoot viewRoot = (ViewRoot)root.getParent();
- if (viewRoot != null) {
- viewRoot.ensureTouchMode(false);
- }
+ ViewRoot viewRoot = getViewRoot();
+ if (viewRoot != null) {
+ viewRoot.ensureTouchMode(false);
}
}
return requestFocus(View.FOCUS_DOWN);
@@ -5150,7 +5153,7 @@
/**
* Recomputes the transform matrix if necessary.
*/
- private final void updateMatrix() {
+ private void updateMatrix() {
if (mMatrixDirty) {
// transform-related properties have changed since the last time someone
// asked for the matrix; recalculate it with the current values
@@ -6205,7 +6208,8 @@
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
}
- if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
+ if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
+ (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
mPrivateFlags &= ~DRAWING_CACHE_VALID;
final ViewParent p = mParent;
final AttachInfo ai = mAttachInfo;
@@ -6236,7 +6240,8 @@
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
}
- if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
+ if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
+ (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
mPrivateFlags &= ~DRAWING_CACHE_VALID;
final ViewParent p = mParent;
final AttachInfo ai = mAttachInfo;
@@ -6275,7 +6280,8 @@
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
}
- if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
+ if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
+ (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID)) {
mPrivateFlags &= ~DRAWN;
if (invalidateCache) {
mPrivateFlags &= ~DRAWING_CACHE_VALID;
@@ -7425,8 +7431,7 @@
final int restoreCount = canvas.save();
- mPrivateFlags |= DRAWN;
- mPrivateFlags |= DRAWING_CACHE_VALID;
+ mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
// Fast path for layouts with no backgrounds
if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
@@ -9833,40 +9838,109 @@
}
/**
+ * !!! TODO: real docs
+ *
+ * The base class implementation makes the thumbnail the same size and appearance
+ * as the view itself, and positions it with its center at the touch point.
+ */
+ public static class DragThumbnailBuilder {
+ private final WeakReference<View> mView;
+
+ /**
+ * Construct a thumbnail builder object for use with the given view.
+ * @param view
+ */
+ public DragThumbnailBuilder(View view) {
+ mView = new WeakReference<View>(view);
+ }
+
+ /**
+ * Provide the draggable-thumbnail metrics for the operation: the dimensions of
+ * the thumbnail image itself, and the point within that thumbnail that should
+ * be centered under the touch location while dragging.
+ * <p>
+ * The default implementation sets the dimensions of the thumbnail to be the
+ * same as the dimensions of the View itself and centers the thumbnail under
+ * the touch point.
+ *
+ * @param thumbnailSize The application should set the {@code x} member of this
+ * parameter to the desired thumbnail width, and the {@code y} member to
+ * the desired height.
+ * @param thumbnailTouchPoint The application should set this point to be the
+ * location within the thumbnail that should track directly underneath
+ * the touch point on the screen during a drag.
+ */
+ public void onProvideThumbnailMetrics(Point thumbnailSize, Point thumbnailTouchPoint) {
+ final View view = mView.get();
+ if (view != null) {
+ thumbnailSize.set(view.getWidth(), view.getHeight());
+ thumbnailTouchPoint.set(thumbnailSize.x / 2, thumbnailSize.y / 2);
+ } else {
+ Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
+ }
+ }
+
+ /**
+ * Draw the thumbnail image for the upcoming drag. The thumbnail canvas was
+ * created with the dimensions supplied by the onProvideThumbnailMetrics()
+ * callback.
+ *
+ * @param canvas
+ */
+ public void onDrawThumbnail(Canvas canvas) {
+ final View view = mView.get();
+ if (view != null) {
+ view.draw(canvas);
+ } else {
+ Log.e(View.VIEW_LOG_TAG, "Asked to draw drag thumb but no view");
+ }
+ }
+ }
+
+ /**
* Drag and drop. App calls startDrag(), then callbacks to onMeasureDragThumbnail()
* and onDrawDragThumbnail() happen, then the drag operation is handed over to the
* OS.
* !!! TODO: real docs
* @hide
*/
- public final boolean startDrag(ClipData data, float touchX, float touchY,
- float thumbnailTouchX, float thumbnailTouchY, boolean myWindowOnly) {
- if (DEBUG_DRAG) {
- Log.d(VIEW_LOG_TAG, "startDrag: touch=(" + touchX + "," + touchY
- + ") thumb=(" + thumbnailTouchX + "," + thumbnailTouchY
- + ") data=" + data + " local=" + myWindowOnly);
+ public final boolean startDrag(ClipData data, DragThumbnailBuilder thumbBuilder,
+ boolean myWindowOnly) {
+ if (ViewDebug.DEBUG_DRAG) {
+ Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " local=" + myWindowOnly);
}
boolean okay = false;
- measureThumbnail(); // throws if the view fails to specify dimensions
+ Point thumbSize = new Point();
+ Point thumbTouchPoint = new Point();
+ thumbBuilder.onProvideThumbnailMetrics(thumbSize, thumbTouchPoint);
+
+ if ((thumbSize.x < 0) || (thumbSize.y < 0) ||
+ (thumbTouchPoint.x < 0) || (thumbTouchPoint.y < 0)) {
+ throw new IllegalStateException("Drag thumb dimensions must not be negative");
+ }
Surface surface = new Surface();
try {
IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
myWindowOnly, mThumbnailWidth, mThumbnailHeight, surface);
- if (DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
+ if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
+ " surface=" + surface);
if (token != null) {
Canvas canvas = surface.lockCanvas(null);
try {
- onDrawDragThumbnail(canvas);
+ thumbBuilder.onDrawThumbnail(canvas);
} finally {
surface.unlockCanvasAndPost(canvas);
}
+ // repurpose 'thumbSize' for the last touch point
+ getViewRoot().getLastTouchPoint(thumbSize);
+
okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
- touchX, touchY, thumbnailTouchX, thumbnailTouchY, data);
- if (DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
+ (float) thumbSize.x, (float) thumbSize.y,
+ (float) thumbTouchPoint.x, (float) thumbTouchPoint.y, data);
+ if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
}
} catch (Exception e) {
Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
@@ -9888,7 +9962,7 @@
+ " measured dimension by calling setDragThumbnailDimension()");
}
- if (DEBUG_DRAG) {
+ if (ViewDebug.DEBUG_DRAG) {
Log.d(VIEW_LOG_TAG, "Drag thumb measured: w=" + mThumbnailWidth
+ " h=" + mThumbnailHeight);
}
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index b1d5272..727cf17 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -136,6 +136,12 @@
public static final boolean DEBUG_SHOW_FPS = false;
/**
+ * Enables detailed logging of drag/drop operations.
+ * @hide
+ */
+ public static final boolean DEBUG_DRAG = true;
+
+ /**
* <p>Enables or disables views consistency check. Even when this property is enabled,
* view consistency checks happen only if {@link android.util.Config#DEBUG} is set
* to true. The value of this property can be configured externally in one of the
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 6c57e1e..5ebc981 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -19,8 +19,6 @@
import android.animation.LayoutTransition;
import com.android.internal.R;
-import android.content.ClipData;
-import android.content.ClipDescription;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
@@ -36,7 +34,6 @@
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Slog;
import android.util.SparseArray;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Animation;
@@ -72,7 +69,6 @@
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
private static final boolean DBG = false;
- private static final String TAG = "ViewGroup";
/**
* Views which have been hidden or removed which need to be animated on
@@ -868,9 +864,7 @@
final float tx = event.mX;
final float ty = event.mY;
- // !!! BUGCHECK: If we have a ViewGroup, we must necessarily have a ViewRoot,
- // so we don't need to check getRootView() for null here?
- ViewRoot root = (ViewRoot)(getRootView().getParent());
+ ViewRoot root = getViewRoot();
// Dispatch down the view hierarchy
switch (event.mAction) {
@@ -883,10 +877,13 @@
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
- final boolean handled = children[i].dispatchDragEvent(event);
- children[i].mCanAcceptDrop = handled;
- if (handled) {
- mChildAcceptsDrag = true;
+ final View child = children[i];
+ if (child.getVisibility() == VISIBLE) {
+ final boolean handled = children[i].dispatchDragEvent(event);
+ children[i].mCanAcceptDrop = handled;
+ if (handled) {
+ mChildAcceptsDrag = true;
+ }
}
}
@@ -901,7 +898,10 @@
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
- children[i].dispatchDragEvent(event);
+ final View child = children[i];
+ if (child.getVisibility() == VISIBLE) {
+ child.dispatchDragEvent(event);
+ }
}
// We consider drag-ended to have been handled if one of our children
// had offered to handle the drag.
@@ -921,7 +921,7 @@
root.setDragFocus(event, target);
mCurrentDragView = target;
}
-
+
// Dispatch the actual drag location notice, localized into its coordinates
if (target != null) {
event.mX = mLocalPoint.x;
@@ -935,7 +935,7 @@
} break;
case DragEvent.ACTION_DROP: {
- if (View.DEBUG_DRAG) Slog.d(TAG, "Drop event: " + event);
+ if (ViewDebug.DEBUG_DRAG) Log.d(View.VIEW_LOG_TAG, "Drop event: " + event);
View target = findFrontmostDroppableChildAt(event.mX, event.mY, mLocalPoint);
if (target != null) {
event.mX = mLocalPoint.x;
@@ -957,30 +957,15 @@
// Find the frontmost child view that lies under the given point, and calculate
// the position within its own local coordinate system.
View findFrontmostDroppableChildAt(float x, float y, PointF outLocalPoint) {
- final float scrolledX = x + mScrollX;
- final float scrolledY = y + mScrollY;
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = count - 1; i >= 0; i--) {
final View child = children[i];
- if (child.mCanAcceptDrop == false) {
+ if (!child.mCanAcceptDrop) {
continue;
}
- float localX = scrolledX - child.mLeft;
- float localY = scrolledY - child.mTop;
- if (!child.hasIdentityMatrix() && mAttachInfo != null) {
- // non-identity matrix: transform the point into the view's coordinates
- final float[] localXY = mAttachInfo.mTmpTransformLocation;
- localXY[0] = localX;
- localXY[1] = localY;
- child.getInverseMatrix().mapPoints(localXY);
- localX = localXY[0];
- localY = localXY[1];
- }
- if (localX >= 0 && localY >= 0 && localX < (child.mRight - child.mLeft) &&
- localY < (child.mBottom - child.mTop)) {
- outLocalPoint.set(localX, localY);
+ if (isTransformedTouchPointInView(x, y, child, outLocalPoint)) {
return child;
}
}
@@ -1108,7 +1093,7 @@
continue;
}
- if (!isTransformedTouchPointInView(x, y, child)) {
+ if (!isTransformedTouchPointInView(x, y, child, null)) {
// New pointer is out of child's bounds.
continue;
}
@@ -1192,16 +1177,20 @@
return handled;
}
- /* Resets all touch state in preparation for a new cycle. */
- private final void resetTouchState() {
+ /**
+ * Resets all touch state in preparation for a new cycle.
+ */
+ private void resetTouchState() {
clearTouchTargets();
resetCancelNextUpFlag(this);
mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
}
- /* Resets the cancel next up flag.
- * Returns true if the flag was previously set. */
- private final boolean resetCancelNextUpFlag(View view) {
+ /**
+ * Resets the cancel next up flag.
+ * Returns true if the flag was previously set.
+ */
+ private boolean resetCancelNextUpFlag(View view) {
if ((view.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
view.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
return true;
@@ -1209,8 +1198,10 @@
return false;
}
- /* Clears all touch targets. */
- private final void clearTouchTargets() {
+ /**
+ * Clears all touch targets.
+ */
+ private void clearTouchTargets() {
TouchTarget target = mFirstTouchTarget;
if (target != null) {
do {
@@ -1222,8 +1213,10 @@
}
}
- /* Cancels and clears all touch targets. */
- private final void cancelAndClearTouchTargets(MotionEvent event) {
+ /**
+ * Cancels and clears all touch targets.
+ */
+ private void cancelAndClearTouchTargets(MotionEvent event) {
if (mFirstTouchTarget != null) {
boolean syntheticEvent = false;
if (event == null) {
@@ -1245,9 +1238,11 @@
}
}
- /* Gets the touch target for specified child view.
- * Returns null if not found. */
- private final TouchTarget getTouchTarget(View child) {
+ /**
+ * Gets the touch target for specified child view.
+ * Returns null if not found.
+ */
+ private TouchTarget getTouchTarget(View child) {
for (TouchTarget target = mFirstTouchTarget; target != null; target = target.next) {
if (target.child == child) {
return target;
@@ -1256,17 +1251,21 @@
return null;
}
- /* Adds a touch target for specified child to the beginning of the list.
- * Assumes the target child is not already present. */
- private final TouchTarget addTouchTarget(View child, int pointerIdBits) {
+ /**
+ * Adds a touch target for specified child to the beginning of the list.
+ * Assumes the target child is not already present.
+ */
+ private TouchTarget addTouchTarget(View child, int pointerIdBits) {
TouchTarget target = TouchTarget.obtain(child, pointerIdBits);
target.next = mFirstTouchTarget;
mFirstTouchTarget = target;
return target;
}
- /* Removes the pointer ids from consideration. */
- private final void removePointersFromTouchTargets(int pointerIdBits) {
+ /**
+ * Removes the pointer ids from consideration.
+ */
+ private void removePointersFromTouchTargets(int pointerIdBits) {
TouchTarget predecessor = null;
TouchTarget target = mFirstTouchTarget;
while (target != null) {
@@ -1289,10 +1288,13 @@
}
}
- /* Returns true if a child view contains the specified point when transformed
+ /**
+ * Returns true if a child view contains the specified point when transformed
* into its coordinate space.
- * Child must not be null. */
- private final boolean isTransformedTouchPointInView(float x, float y, View child) {
+ * Child must not be null.
+ */
+ private boolean isTransformedTouchPointInView(float x, float y, View child,
+ PointF outLocalPoint) {
float localX = x + mScrollX - child.mLeft;
float localY = y + mScrollY - child.mTop;
if (! child.hasIdentityMatrix() && mAttachInfo != null) {
@@ -1303,13 +1305,19 @@
localX = localXY[0];
localY = localXY[1];
}
- return child.pointInView(localX, localY);
+ final boolean isInView = child.pointInView(localX, localY);
+ if (isInView && outLocalPoint != null) {
+ outLocalPoint.set(localX, localY);
+ }
+ return isInView;
}
- /* Transforms a motion event into the coordinate space of a particular child view,
+ /**
+ * Transforms a motion event into the coordinate space of a particular child view,
* filters out irrelevant pointer ids, and overrides its action if necessary.
- * If child is null, assumes the MotionEvent will be sent to this ViewGroup instead. */
- private final boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
+ * If child is null, assumes the MotionEvent will be sent to this ViewGroup instead.
+ */
+ private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
final boolean handled;
@@ -1484,9 +1492,11 @@
return handled;
}
- /* Enlarge the temporary pointer arrays for splitting pointers.
- * May discard contents (but keeps PointerCoords objects to avoid reallocating them). */
- private final void growTmpPointerArrays(int desiredCapacity) {
+ /**
+ * Enlarge the temporary pointer arrays for splitting pointers.
+ * May discard contents (but keeps PointerCoords objects to avoid reallocating them).
+ */
+ private void growTmpPointerArrays(int desiredCapacity) {
final MotionEvent.PointerCoords[] oldTmpPointerCoords = mTmpPointerCoords;
int capacity;
if (oldTmpPointerCoords != null) {
@@ -2182,7 +2192,8 @@
if (!canvas.isHardwareAccelerated()) {
cache = child.getDrawingCache(true);
} else {
- displayList = child.getDisplayList();
+ // TODO: bring back
+ // displayList = child.getDisplayList();
}
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index c63f7d6..155122f 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -24,6 +24,7 @@
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
+import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
@@ -205,6 +206,7 @@
ClipDescription mDragDescription;
View mCurrentDragView;
final PointF mDragPoint = new PointF();
+ final PointF mLastTouchPoint = new PointF();
/**
* see {@link #playSoundEffect(int)}
@@ -2024,6 +2026,9 @@
if (MEASURE_LATENCY) {
lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
}
+ // cache for possible drag-initiation
+ mLastTouchPoint.x = event.getRawX();
+ mLastTouchPoint.y = event.getRawY();
handled = mView.dispatchTouchEvent(event);
if (MEASURE_LATENCY) {
lt.sample("B Dispatched TouchEvents ", System.nanoTime() - event.getEventTimeNano());
@@ -2509,6 +2514,11 @@
event.recycle();
}
+ public void getLastTouchPoint(Point outLocation) {
+ outLocation.x = (int) mLastTouchPoint.x;
+ outLocation.y = (int) mLastTouchPoint.y;
+ }
+
public void setDragFocus(DragEvent event, View newDragTarget) {
final int action = event.mAction;
// If we've dragged off of a view, send it the EXITED message
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index 8ffa158..3e2e92b 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -28,6 +28,11 @@
* A special helper class used by the WindowManager
* for receiving notifications from the SensorManager when
* the orientation of the device has changed.
+ *
+ * NOTE: If changing anything here, please run the API demo
+ * "App/Activity/Screen Orientation" to ensure that all orientation
+ * modes still work correctly.
+ *
* @hide
*/
public abstract class WindowOrientationListener {
@@ -103,6 +108,10 @@
}
}
+ public void setAllow180Rotation(boolean allowed) {
+ mSensorEventListener.setAllow180Rotation(allowed);
+ }
+
public int getCurrentRotation(int lastRotation) {
if (mEnabled) {
return mSensorEventListener.getCurrentRotation(lastRotation);
@@ -151,19 +160,20 @@
private static final int ROTATION_0 = 0;
private static final int ROTATION_90 = 1;
private static final int ROTATION_270 = 2;
+ private static final int ROTATION_180 = 3;
// Mapping our internal aliases into actual Surface rotation values
private static final int[] INTERNAL_TO_SURFACE_ROTATION = new int[] {
- Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270};
+ Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270,
+ Surface.ROTATION_180};
// Mapping Surface rotation values to internal aliases.
- // We have no constant for Surface.ROTATION_180. That should never happen, but if it
- // does, we'll arbitrarily choose a mapping.
private static final int[] SURFACE_TO_INTERNAL_ROTATION = new int[] {
- ROTATION_0, ROTATION_90, ROTATION_90, ROTATION_270};
+ ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270};
// Threshold ranges of orientation angle to transition into other orientation states.
- // The first list is for transitions from ROTATION_0, the next for ROTATION_90, etc.
+ // The first list is for transitions from ROTATION_0, ROTATION_90, ROTATION_270,
+ // and then ROTATION_180.
// ROTATE_TO defines the orientation each threshold range transitions to, and must be kept
// in sync with this.
// We generally transition about the halfway point between two states with a swing of 30
@@ -172,13 +182,32 @@
{{60, 180}, {180, 300}},
{{0, 30}, {195, 315}, {315, 360}},
{{0, 45}, {45, 165}, {330, 360}},
- };
+ // Handle situation where we are currently doing 180 rotation
+ // but that is no longer allowed.
+ {{0, 45}, {45, 135}, {135, 225}, {225, 315}, {315, 360}},
+ };
// See THRESHOLDS
private static final int[][] ROTATE_TO = new int[][] {
{ROTATION_90, ROTATION_270},
{ROTATION_0, ROTATION_270, ROTATION_0},
{ROTATION_0, ROTATION_90, ROTATION_0},
+ {ROTATION_0, ROTATION_90, ROTATION_0, ROTATION_270, ROTATION_0},
+ };
+
+ // Thresholds that allow all 4 orientations.
+ private static final int[][][] THRESHOLDS_WITH_180 = new int[][][] {
+ {{60, 165}, {165, 195}, {195, 300}},
+ {{0, 30}, {165, 195}, {195, 315}, {315, 360}},
+ {{0, 45}, {45, 165}, {165, 195}, {330, 360}},
+ {{0, 45}, {45, 135}, {225, 315}, {315, 360}},
+ };
+ // See THRESHOLDS_WITH_180
+ private static final int[][] ROTATE_TO_WITH_180 = new int[][] {
+ {ROTATION_90, ROTATION_180, ROTATION_270},
+ {ROTATION_0, ROTATION_180, ROTATION_90, ROTATION_0},
+ {ROTATION_0, ROTATION_270, ROTATION_180, ROTATION_0},
+ {ROTATION_0, ROTATION_90, ROTATION_270, ROTATION_0},
};
// Maximum absolute tilt angle at which to consider orientation data. Beyond this (i.e.
@@ -188,7 +217,7 @@
// Additional limits on tilt angle to transition to each new orientation. We ignore all
// data with tilt beyond MAX_TILT, but we can set stricter limits on transitions to a
// particular orientation here.
- private static final int[] MAX_TRANSITION_TILT = new int[] {MAX_TILT, 65, 65};
+ private static final int[] MAX_TRANSITION_TILT = new int[] {MAX_TILT, 65, 65, 40};
// Between this tilt angle and MAX_TILT, we'll allow orientation changes, but we'll filter
// with a higher time constant, making us less sensitive to change. This primarily helps
@@ -228,6 +257,8 @@
private static final float ACCELERATING_LOWPASS_ALPHA =
computeLowpassAlpha(ACCELERATING_TIME_CONSTANT_MS);
+ private boolean mAllow180Rotation = false;
+
private WindowOrientationListener mOrientationListener;
private int mRotation = ROTATION_0; // Current orientation state
private float mTiltAngle = 0; // low-pass filtered
@@ -249,6 +280,10 @@
return (float) SAMPLING_PERIOD_MS / (timeConstantMs + SAMPLING_PERIOD_MS);
}
+ void setAllow180Rotation(boolean allowed) {
+ mAllow180Rotation = allowed;
+ }
+
int getCurrentRotation(int lastRotation) {
if (mTiltDistrust > 0) {
// we really don't know the current orientation, so trust what's currently displayed
@@ -259,7 +294,9 @@
private void calculateNewRotation(float orientation, float tiltAngle) {
if (localLOGV) Log.i(TAG, orientation + ", " + tiltAngle + ", " + mRotation);
- int thresholdRanges[][] = THRESHOLDS[mRotation];
+ final boolean allow180Rotation = mAllow180Rotation;
+ int thresholdRanges[][] = allow180Rotation
+ ? THRESHOLDS_WITH_180[mRotation] : THRESHOLDS[mRotation];
int row = -1;
for (int i = 0; i < thresholdRanges.length; i++) {
if (orientation >= thresholdRanges[i][0] && orientation < thresholdRanges[i][1]) {
@@ -269,13 +306,15 @@
}
if (row == -1) return; // no matching transition
- int rotation = ROTATE_TO[mRotation][row];
+ int rotation = allow180Rotation
+ ? ROTATE_TO_WITH_180[mRotation][row] : ROTATE_TO[mRotation][row];
if (tiltAngle > MAX_TRANSITION_TILT[rotation]) {
// tilted too far flat to go to this rotation
return;
}
- if (localLOGV) Log.i(TAG, " new rotation = " + rotation);
+ if (localLOGV) Log.i(TAG, "orientation " + orientation + " gives new rotation = "
+ + rotation);
mRotation = rotation;
mOrientationListener.onOrientationChanged(INTERNAL_TO_SURFACE_ROTATION[mRotation]);
}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 20aafbd..7b9af5b 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1081,6 +1081,7 @@
if (mBlockNetworkLoads != flag) {
mBlockNetworkLoads = flag;
verifyNetworkAccess();
+ postSync();
}
}
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 9983d54..1d1e601 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -19,6 +19,7 @@
import java.util.ArrayList;
import java.util.HashMap;
+import android.animation.AnimatorInflater;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.Intent;
@@ -135,12 +136,15 @@
int mReferenceChildHeight = -1;
/**
- * TODO: Animation stuff is still in flux, waiting on the new framework to settle a bit.
+ * In and out animations.
*/
- Animation mInAnimation;
- Animation mOutAnimation;
+ ObjectAnimator<?> mInAnimation;
+ ObjectAnimator<?> mOutAnimation;
+
private ArrayList<View> mViewsToBringToFront;
+ private static final int DEFAULT_ANIMATION_DURATION = 200;
+
public AdapterViewAnimator(Context context) {
super(context);
initViewAnimator();
@@ -155,11 +159,15 @@
com.android.internal.R.styleable.AdapterViewAnimator_inAnimation, 0);
if (resource > 0) {
setInAnimation(context, resource);
+ } else {
+ setInAnimation(getDefaultInAnimation());
}
resource = a.getResourceId(com.android.internal.R.styleable.AdapterViewAnimator_outAnimation, 0);
if (resource > 0) {
setOutAnimation(context, resource);
+ } else {
+ setOutAnimation(getDefaultOutAnimation());
}
boolean flag = a.getBoolean(
@@ -229,17 +237,23 @@
* @param view The view that is being animated
*/
void animateViewForTransition(int fromIndex, int toIndex, View view) {
- ObjectAnimator pa;
if (fromIndex == -1) {
- view.setAlpha(0.0f);
- pa = new ObjectAnimator(400, view, "alpha", 0.0f, 1.0f);
- pa.start();
+ mInAnimation.setTarget(view);
+ mInAnimation.start();
} else if (toIndex == -1) {
- pa = new ObjectAnimator(400, view, "alpha", 1.0f, 0.0f);
- pa.start();
+ mOutAnimation.setTarget(view);
+ mOutAnimation.start();
}
}
+ ObjectAnimator<?> getDefaultInAnimation() {
+ return new ObjectAnimator<Float>(DEFAULT_ANIMATION_DURATION, null, "alpha", 0.0f, 1.0f);
+ }
+
+ ObjectAnimator<?> getDefaultOutAnimation() {
+ return new ObjectAnimator<Float>(DEFAULT_ANIMATION_DURATION, null, "alpha", 1.0f, 0.0f);
+ }
+
/**
* Sets which child view will be displayed.
*
@@ -265,20 +279,6 @@
}
/**
- * Return default inAnimation. To be overriden by subclasses.
- */
- Animation getDefaultInAnimation() {
- return null;
- }
-
- /**
- * Return default outAnimation. To be overridden by subclasses.
- */
- Animation getDefaultOutAnimation() {
- return null;
- }
-
- /**
* To be overridden by subclasses. This method applies a view / index specific
* transform to the child view.
*
@@ -690,7 +690,7 @@
* @see #setInAnimation(android.view.animation.Animation)
* @see #setInAnimation(android.content.Context, int)
*/
- public Animation getInAnimation() {
+ public ObjectAnimator<?> getInAnimation() {
return mInAnimation;
}
@@ -702,7 +702,7 @@
* @see #getInAnimation()
* @see #setInAnimation(android.content.Context, int)
*/
- public void setInAnimation(Animation inAnimation) {
+ public void setInAnimation(ObjectAnimator<?> inAnimation) {
mInAnimation = inAnimation;
}
@@ -714,7 +714,7 @@
* @see #setOutAnimation(android.view.animation.Animation)
* @see #setOutAnimation(android.content.Context, int)
*/
- public Animation getOutAnimation() {
+ public ObjectAnimator<?> getOutAnimation() {
return mOutAnimation;
}
@@ -726,7 +726,7 @@
* @see #getOutAnimation()
* @see #setOutAnimation(android.content.Context, int)
*/
- public void setOutAnimation(Animation outAnimation) {
+ public void setOutAnimation(ObjectAnimator<?> outAnimation) {
mOutAnimation = outAnimation;
}
@@ -740,7 +740,7 @@
* @see #setInAnimation(android.view.animation.Animation)
*/
public void setInAnimation(Context context, int resourceID) {
- setInAnimation(AnimationUtils.loadAnimation(context, resourceID));
+ setInAnimation((ObjectAnimator<?>) AnimatorInflater.loadAnimator(context, resourceID));
}
/**
@@ -753,7 +753,7 @@
* @see #setOutAnimation(android.view.animation.Animation)
*/
public void setOutAnimation(Context context, int resourceID) {
- setOutAnimation(AnimationUtils.loadAnimation(context, resourceID));
+ setOutAnimation((ObjectAnimator<?>) AnimatorInflater.loadAnimator(context, resourceID));
}
/**
diff --git a/core/java/android/widget/AdapterViewFlipper.java b/core/java/android/widget/AdapterViewFlipper.java
index 95ebdd3..b09ade7 100644
--- a/core/java/android/widget/AdapterViewFlipper.java
+++ b/core/java/android/widget/AdapterViewFlipper.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.animation.ObjectAnimator;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -43,10 +44,8 @@
private static final boolean LOGD = false;
private static final int DEFAULT_INTERVAL = 10000;
- private static final int DEFAULT_ANIMATION_DURATION = 200;
private int mFlipInterval = DEFAULT_INTERVAL;
- private int mAnimationDuration = DEFAULT_ANIMATION_DURATION;
private boolean mAutoStart = false;
private boolean mRunning = false;
@@ -56,7 +55,6 @@
public AdapterViewFlipper(Context context) {
super(context);
- initDefaultAnimations();
}
public AdapterViewFlipper(Context context, AttributeSet attrs) {
@@ -74,19 +72,6 @@
com.android.internal.R.styleable.AdapterViewAnimator_loopViews, true);
a.recycle();
- initDefaultAnimations();
- }
-
- private void initDefaultAnimations() {
- // Set the default animations to be fade in/out
- if (mInAnimation == null) {
- mInAnimation = new AlphaAnimation(0.0f, 1.0f);
- mInAnimation.setDuration(mAnimationDuration);
- }
- if (mOutAnimation == null) {
- mOutAnimation = new AlphaAnimation(1.0f, 0.0f);
- mOutAnimation.setDuration(mAnimationDuration);
- }
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 4a0617c..fefdcea 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -17,6 +17,9 @@
package com.android.internal.app;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
+import com.android.internal.R;
+
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -32,10 +35,11 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
-import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckedTextView;
@@ -48,9 +52,6 @@
import android.widget.ScrollView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
-
-import com.android.internal.R;
import java.lang.ref.WeakReference;
@@ -403,12 +404,10 @@
mIconView = (ImageView) mWindow.findViewById(R.id.icon);
if (hasTextTitle) {
-
/* Display the title if a title is supplied, else hide it */
mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle);
mTitleView.setText(mTitle);
- mIconView.setImageResource(R.drawable.ic_dialog_menu_generic);
/* Do this last so that if the user has supplied any
* icons we use them instead of the default ones. If the
@@ -689,7 +688,7 @@
public final Context mContext;
public final LayoutInflater mInflater;
- public int mIconId = -1;
+ public int mIconId = 0;
public Drawable mIcon;
public CharSequence mTitle;
public View mCustomTitleView;
diff --git a/core/res/res/anim/fragment_close_enter.xml b/core/res/res/anim/fragment_close_enter.xml
index 53afa2a..7a9a3b9 100644
--- a/core/res/res/anim/fragment_close_enter.xml
+++ b/core/res/res/anim/fragment_close_enter.xml
@@ -19,20 +19,6 @@
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:interpolator="@anim/decelerate_interpolator"
- android:valueFrom="2"
- android:valueTo="1"
- android:valueType="floatType"
- android:propertyName="scaleX"
- android:duration="@android:integer/config_mediumAnimTime"/>
- <objectAnimator
- android:interpolator="@anim/decelerate_interpolator"
- android:valueFrom="2"
- android:valueTo="1"
- android:valueType="floatType"
- android:propertyName="scaleY"
- android:duration="@android:integer/config_mediumAnimTime"/>
- <objectAnimator
- android:interpolator="@anim/decelerate_interpolator"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
diff --git a/core/res/res/anim/fragment_close_exit.xml b/core/res/res/anim/fragment_close_exit.xml
index 1554a4e..0743577 100644
--- a/core/res/res/anim/fragment_close_exit.xml
+++ b/core/res/res/anim/fragment_close_exit.xml
@@ -20,20 +20,6 @@
<objectAnimator
android:interpolator="@anim/accelerate_interpolator"
android:valueFrom="1"
- android:valueTo=".5"
- android:valueType="floatType"
- android:propertyName="scaleX"
- android:duration="@android:integer/config_mediumAnimTime"/>
- <objectAnimator
- android:interpolator="@anim/accelerate_interpolator"
- android:valueFrom="1"
- android:valueTo=".5"
- android:valueType="floatType"
- android:propertyName="scaleY"
- android:duration="@android:integer/config_mediumAnimTime"/>
- <objectAnimator
- android:interpolator="@anim/accelerate_interpolator"
- android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
android:propertyName="alpha"
diff --git a/core/res/res/anim/fragment_next_enter.xml b/core/res/res/anim/fragment_next_enter.xml
new file mode 100644
index 0000000..d2d6ec9
--- /dev/null
+++ b/core/res/res/anim/fragment_next_enter.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, 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.
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType"
+ android:propertyName="alpha"
+ android:duration="@android:integer/config_longAnimTime"/>
+ <objectAnimator
+ android:valueFrom="50"
+ android:valueTo="0"
+ android:valueType="floatType"
+ android:propertyName="translationY"
+ android:duration="@android:integer/config_longAnimTime"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_next_exit.xml b/core/res/res/anim/fragment_next_exit.xml
new file mode 100644
index 0000000..fbb82d9
--- /dev/null
+++ b/core/res/res/anim/fragment_next_exit.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, 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.
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:valueFrom="1"
+ android:valueTo="0"
+ android:valueType="floatType"
+ android:propertyName="alpha"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+ <objectAnimator
+ android:valueFrom="0"
+ android:valueTo="-50"
+ android:valueType="floatType"
+ android:propertyName="translationY"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_enter.xml b/core/res/res/anim/fragment_open_enter.xml
index 142f60c..ac60494 100644
--- a/core/res/res/anim/fragment_open_enter.xml
+++ b/core/res/res/anim/fragment_open_enter.xml
@@ -18,20 +18,6 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
- android:interpolator="@anim/decelerate_interpolator"
- android:valueFrom="2"
- android:valueTo="1"
- android:valueType="floatType"
- android:propertyName="scaleX"
- android:duration="@android:integer/config_mediumAnimTime"/>
- <objectAnimator
- android:interpolator="@anim/decelerate_interpolator"
- android:valueFrom="2"
- android:valueTo="1"
- android:valueType="floatType"
- android:propertyName="scaleY"
- android:duration="@android:integer/config_mediumAnimTime"/>
- <objectAnimator
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
diff --git a/core/res/res/anim/fragment_open_exit.xml b/core/res/res/anim/fragment_open_exit.xml
index 21260b9..3bf1ad4 100644
--- a/core/res/res/anim/fragment_open_exit.xml
+++ b/core/res/res/anim/fragment_open_exit.xml
@@ -18,20 +18,6 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
- android:interpolator="@anim/accelerate_interpolator"
- android:valueFrom="1"
- android:valueTo="2"
- android:valueType="floatType"
- android:propertyName="scaleX"
- android:duration="@android:integer/config_mediumAnimTime"/>
- <objectAnimator
- android:interpolator="@anim/accelerate_interpolator"
- android:valueFrom="1"
- android:valueTo="2"
- android:valueType="floatType"
- android:propertyName="scaleY"
- android:duration="@android:integer/config_mediumAnimTime"/>
- <objectAnimator
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
diff --git a/core/res/res/anim/fragment_prev_enter.xml b/core/res/res/anim/fragment_prev_enter.xml
new file mode 100644
index 0000000..d37afd0
--- /dev/null
+++ b/core/res/res/anim/fragment_prev_enter.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, 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.
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType"
+ android:propertyName="alpha"
+ android:duration="@android:integer/config_longAnimTime"/>
+ <objectAnimator
+ android:valueFrom="-50"
+ android:valueTo="0"
+ android:valueType="floatType"
+ android:propertyName="translationY"
+ android:duration="@android:integer/config_longAnimTime"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_prev_exit.xml b/core/res/res/anim/fragment_prev_exit.xml
new file mode 100644
index 0000000..a445a4d
--- /dev/null
+++ b/core/res/res/anim/fragment_prev_exit.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, 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.
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:valueFrom="1"
+ android:valueTo="0"
+ android:valueType="floatType"
+ android:propertyName="alpha"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+ <objectAnimator
+ android:valueFrom="0"
+ android:valueTo="50"
+ android:valueType="floatType"
+ android:propertyName="translationY"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/drawable-hdpi/ic_dialog_menu_generic.png b/core/res/res/drawable-hdpi/ic_dialog_menu_generic.png
deleted file mode 100644
index ef8a877..0000000
--- a/core/res/res/drawable-hdpi/ic_dialog_menu_generic.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_100.png b/core/res/res/drawable-hdpi/stat_sys_battery_100.png
index e85f524..e49448d 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_100.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_40.png b/core/res/res/drawable-hdpi/stat_sys_battery_40.png
index ca70784..441bbfb 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_40.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_40.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_60.png b/core/res/res/drawable-hdpi/stat_sys_battery_60.png
index fee28db..d9467ed 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_60.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_60.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_80.png b/core/res/res/drawable-hdpi/stat_sys_battery_80.png
index 7f4a38f..e3f4805 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_80.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_80.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim2.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim2.png
index 2277096..426a66b 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim2.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim3.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim3.png
index 7a3b19e..21582ca 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim3.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim4.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim4.png
index 5c23c13..8a94763 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim4.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim5.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim5.png
index 321545f..fad0d65 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim5.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim1.png b/core/res/res/drawable-hdpi/stat_sys_download_anim1.png
index 4f47db0..851eff9 100755
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim1.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim2.png b/core/res/res/drawable-hdpi/stat_sys_download_anim2.png
index e50d3c3..2d06bb1 100755
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim2.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim3.png b/core/res/res/drawable-hdpi/stat_sys_download_anim3.png
index 6c1029c..5c0ae7a 100755
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim3.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim4.png b/core/res/res/drawable-hdpi/stat_sys_download_anim4.png
index 693f085..f8d5c8a 100755
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim4.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim5.png b/core/res/res/drawable-hdpi/stat_sys_download_anim5.png
index eabe0ef..32b1425 100755
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim5.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png
index d72afbe..32b5077 100755
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
index 5de2873..8387b45 100755
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png
index dd0b49f..c9a56a0 100755
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png
index 8ac29b3..972808a 100755
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png
index 26c3e714..d47c761 100755
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png
index 431ac6b..7aeafbe 100755
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_menu_generic.png b/core/res/res/drawable-mdpi/ic_dialog_menu_generic.png
deleted file mode 100755
index de07bda..0000000
--- a/core/res/res/drawable-mdpi/ic_dialog_menu_generic.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 8e2b762..33d3eeb 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1088,6 +1088,10 @@
<attr name="fragmentOpenExitAnimation" format="reference" />
<attr name="fragmentCloseEnterAnimation" format="reference" />
<attr name="fragmentCloseExitAnimation" format="reference" />
+ <attr name="fragmentNextEnterAnimation" format="reference" />
+ <attr name="fragmentNextExitAnimation" format="reference" />
+ <attr name="fragmentPrevEnterAnimation" format="reference" />
+ <attr name="fragmentPrevExitAnimation" format="reference" />
</declare-styleable>
<!-- Window animation class attributes. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 8cf65ae..949d960 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -497,10 +497,10 @@
orientation will changed based on how the user rotates the device -->
<enum name="unspecified" value="-1" />
<!-- Would like to have the screen in a landscape orientation: that
- is, with the display wider than it is tall. -->
+ is, with the display wider than it is tall, ignoring sensor data. -->
<enum name="landscape" value="0" />
<!-- Would like to have the screen in a portrait orientation: that
- is, with the display taller than it is wide. -->
+ is, with the display taller than it is wide, ignoring sensor data. -->
<enum name="portrait" value="1" />
<!-- Use the user's current preferred orientation of the handset. -->
<enum name="user" value="2" />
@@ -513,6 +513,24 @@
<!-- Always ignore orientation determined by orientation sensor:
the display will not rotate when the user moves the device. -->
<enum name="nosensor" value="5" />
+ <!-- Would like to have the screen in landscape orientation, but can
+ use the sensor to change which direction the screen is facing. -->
+ <enum name="sensorLandscape" value="6" />
+ <!-- Would like to have the screen in portrait orientation, but can
+ use the sensor to change which direction the screen is facing. -->
+ <enum name="sensorPortait" value="7" />
+ <!-- Would like to have the screen in landscape orientation, turned in
+ the opposite direction from normal landscape. -->
+ <enum name="reverseLandscape" value="8" />
+ <!-- Would like to have the screen in portrait orientation, turned in
+ the opposite direction from normal portrait. -->
+ <enum name="reversePortait" value="9" />
+ <!-- Orientation is determined by a physical orientation sensor:
+ the display will rotate based on how the user moves the device.
+ This allows any of the 4 possible rotations, regardless of what
+ the device will normally do (for example some devices won't
+ normally use 180 degree rotation). -->
+ <enum name="fullSensor" value="10" />
</attr>
<!-- Specify one or more configuration changes that the activity will
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 35f8df5..2c3c4fc 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1332,6 +1332,10 @@
<public type="attr" name="fragmentOpenExitAnimation" />
<public type="attr" name="fragmentCloseEnterAnimation" />
<public type="attr" name="fragmentCloseExitAnimation" />
+ <public type="attr" name="fragmentNextEnterAnimation" />
+ <public type="attr" name="fragmentNextExitAnimation" />
+ <public type="attr" name="fragmentPrevEnterAnimation" />
+ <public type="attr" name="fragmentPrevExitAnimation" />
<public type="attr" name="actionBarSize" />
<public type="attr" name="imeSubtypeLocale" />
<public type="attr" name="imeSubtypeMode" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 3dfaf7f..4b5047e 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -78,6 +78,10 @@
<item name="fragmentOpenExitAnimation">@anim/fragment_open_exit</item>
<item name="fragmentCloseEnterAnimation">@anim/fragment_close_enter</item>
<item name="fragmentCloseExitAnimation">@anim/fragment_close_exit</item>
+ <item name="fragmentNextEnterAnimation">@anim/fragment_next_enter</item>
+ <item name="fragmentNextExitAnimation">@anim/fragment_next_exit</item>
+ <item name="fragmentPrevEnterAnimation">@anim/fragment_prev_enter</item>
+ <item name="fragmentPrevExitAnimation">@anim/fragment_prev_exit</item>
</style>
<!-- Standard animations for a non-full-screen window or activity. -->
diff --git a/docs/html/guide/appendix/market-filters.jd b/docs/html/guide/appendix/market-filters.jd
index 0797892..e74cefb 100644
--- a/docs/html/guide/appendix/market-filters.jd
+++ b/docs/html/guide/appendix/market-filters.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
-<h2 align="left">Market filters quickview</h2>
+<h2>Quickview</h2>
<ul> <li>Android Market applies filters to that let you control whether your app is shown to a
user who is browing or searching for apps.</li>
<li>Filtering is determined by elements in an app's manifest file,
diff --git a/docs/html/guide/practices/design/performance.jd b/docs/html/guide/practices/design/performance.jd
index 56872a7..f5588ac 100644
--- a/docs/html/guide/practices/design/performance.jd
+++ b/docs/html/guide/practices/design/performance.jd
@@ -1,6 +1,30 @@
page.title=Designing for Performance
@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+<ol>
+ <li><a href="#intro">Introduction</a></li>
+ <li><a href="#optimize_judiciously">Optimize Judiciously</a></li>
+ <li><a href="#object_creation">Avoid Creating Objects</a></li>
+ <li><a href="#myths">Performance Myths</a></li>
+ <li><a href="#prefer_static">Prefer Static Over Virtual</a></li>
+ <li><a href="#internal_get_set">Avoid Internal Getters/Setters</a></li>
+ <li><a href="#use_final">Use Static Final For Constants</a></li>
+ <li><a href="#foreach">Use Enhanced For Loop Syntax</a></li>
+ <li><a href="#avoid_enums">Avoid Enums Where You Only Need Ints</a></li>
+ <li><a href="#package_inner">Use Package Scope with Inner Classes</a></li>
+ <li><a href="#avoidfloat">Use Floating-Point Judiciously</a> </li>
+ <li><a href="#library">Know And Use The Libraries</a></li>
+ <li><a href="#native_methods">Use Native Methods Judiciously</a></li>
+ <li><a href="#closing_notes">Closing Notes</a></li>
+</ol>
+
+</div>
+</div>
+
<p>An Android application will run on a mobile device with limited computing
power and storage, and constrained battery life. Because of
this, it should be <em>efficient</em>. Battery life is one reason you might
@@ -8,24 +32,6 @@
Battery life is important to users, and Android's battery usage breakdown
means users will know if your app is responsible draining their battery.</p>
-<p>This document covers these topics: </p>
-<ul>
- <li><a href="#intro">Introduction</a></li>
- <li><a href="#optimize_judiciously">Optimize Judiciously</a></li>
- <li><a href="#object_creation">Avoid Creating Objects</a></li>
- <li><a href="#myths">Performance Myths</a></li>
- <li><a href="#prefer_static">Prefer Static Over Virtual</a></li>
- <li><a href="#internal_get_set">Avoid Internal Getters/Setters</a></li>
- <li><a href="#use_final">Use Static Final For Constants</a></li>
- <li><a href="#foreach">Use Enhanced For Loop Syntax</a></li>
- <li><a href="#avoid_enums">Avoid Enums Where You Only Need Ints</a></li>
- <li><a href="#package_inner">Use Package Scope with Inner Classes</a></li>
- <li><a href="#avoidfloat">Use Floating-Point Judiciously</a> </li>
- <li><a href="#library">Know And Use The Libraries</a></li>
- <li><a href="#native_methods">Use Native Methods Judiciously</a></li>
- <li><a href="#closing_notes">Closing Notes</a></li>
-</ul>
-
<p>Note that although this document primarily covers micro-optimizations,
these will almost never make or break your software. Choosing the right
algorithms and data structures should always be your priority, but is
diff --git a/docs/html/guide/practices/design/responsiveness.jd b/docs/html/guide/practices/design/responsiveness.jd
index 9858e36..b811d1b 100644
--- a/docs/html/guide/practices/design/responsiveness.jd
+++ b/docs/html/guide/practices/design/responsiveness.jd
@@ -1,6 +1,19 @@
page.title=Designing for Responsiveness
@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+<ol>
+ <li><a href="#anr">What Triggers ANR?</a></li>
+ <li><a href="#avoiding">How to Avoid ANR</a></li>
+ <li><a href="#reinforcing">Reinforcing Responsiveness</a></li>
+</ol>
+
+</div>
+</div>
+
<div class="figure">
<img src="{@docRoot}images/anr.png" alt="Screenshot of ANR dialog box" width="240" height="320"/>
<p><strong>Figure 1.</strong> An ANR dialog displayed to the user.</p>
diff --git a/docs/html/guide/practices/design/seamlessness.jd b/docs/html/guide/practices/design/seamlessness.jd
index a6c1641..dedc16f 100644
--- a/docs/html/guide/practices/design/seamlessness.jd
+++ b/docs/html/guide/practices/design/seamlessness.jd
@@ -1,6 +1,26 @@
page.title=Designing for Seamlessness
@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+<ol>
+ <li><a href="#drop">Don't Drop Data</a></li>
+ <li><a href="#expose">Don't Expose Raw Data</a></li>
+ <li><a href="#interrupt">Don't Interrupt the User</a></li>
+ <li><a href="#threads">Got a Lot to Do? Do it in a Thread</a></li>
+ <li><a href="#multiple-activities">Don't Overload a Single Activity Screen</a></li>
+ <li><a href="#themes">Extend System Themes</a></li>
+ <li><a href="#flexui">Design Your UI to Work with Multiple Screen Resolutions</a></li>
+ <li><a href="#network">Assume the Network is Slow</a></li>
+ <li><a href="#keyboard">Don't Assume Touchscreen or Keyboard</a></li>
+ <li><a href="#battery">Do Conserve the Device Battery</a></li>
+</ol>
+
+</div>
+</div>
+
<p>Even if your application is fast and responsive, certain design decisions can
still cause problems for users — because of unplanned interactions with
other applications or dialogs, inadvertent loss of data, unintended blocking,
@@ -42,20 +62,7 @@
by allowing you to integrate cleanly and seamlessly with other applications, and
so you should design your own code to return the favor.</p>
-<p>This document discusses common seamlessness problems and how to avoid them.
-It covers these topics: </p>
-<ul>
- <li><a href="#drop">Don't Drop Data</a></li>
- <li><a href="#expose">Don't Expose Raw Data</a></li>
- <li><a href="#interrupt">Don't Interrupt the User</a></li>
- <li><a href="#threads">Got a Lot to Do? Do it in a Thread</a></li>
- <li><a href="#multiple-activities">Don't Overload a Single Activity Screen</a></li>
- <li><a href="#themes">Extend System Themes</a></li>
- <li><a href="#flexui">Design Your UI to Work with Multiple Screen Resolutions</a></li>
- <li><a href="#network">Assume the Network is Slow</a></li>
- <li><a href="#keyboard">Don't Assume Touchscreen or Keyboard</a></li>
- <li><a href="#battery">Do Conserve the Device Battery</a></li>
-</ul>
+<p>This document discusses common seamlessness problems and how to avoid them.</p>
<h2 id="drop">Don't Drop Data</h2>
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 11ad1b8..13b5e3a 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -5,7 +5,7 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>Multiple screens quickview: </h2>
+ <h2>Quickview</h2>
<ul>
<li>Android runs on devices that have different screen sizes and resolutions.</li>
<li>The screen on which your application is displayed can affect its user interface.</li>
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 c8d241c..6cb98e6 100644
--- a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Activity and task design quickview</h2>
+<h2>Quickview</h2>
<ul>
<li>Activities are the main building blocks of Android applications. </li>
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design.jd b/docs/html/guide/practices/ui_guidelines/icon_design.jd
index 51ccfaf..389d5fa 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Icon design quickview</h2>
+<h2>Quickview</h2>
<ul>
<li>You can use several types of icons in an Android application.</li>
@@ -35,25 +35,30 @@
</ol>
-<h2>See also</h2>
-
-<ol>
-<li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
-Screens</a></li>
-<li><a href="{@docRoot}shareables/icon_templates-v2.0.zip">Android Icon
-Templates Pack, v2.0 »</a></li>
-</ol>
-
<h2>Older versions</h2>
<ol>
<li style="margin-top:4px;"><a
href="{@docRoot}guide/practices/ui_guidelines/icon_design_1.html">Icon Design
Guidelines, Android 1.0</a></li>
+</ol>
+
+<h2>Downloads</h2>
+
+<ol>
+<li><a href="{@docRoot}shareables/icon_templates-v2.0.zip">Android Icon
+Templates Pack, v2.0 »</a></li>
<li><a href="{@docRoot}shareables/icon_templates-v1.0.zip">Android Icon
Templates Pack, v1.0 »</a></li>
</ol>
+<h2>See also</h2>
+
+<ol>
+<li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
+Screens</a></li>
+</ol>
+
</div>
</div>
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_1.jd b/docs/html/guide/practices/ui_guidelines/icon_design_1.jd
index 1c75843..995cfea 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_1.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_1.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Icon design quickview</h2>
+<h2>Quickview</h2>
<ul>
<li>You can use several types of icons in an Android application.</li>
@@ -35,12 +35,17 @@
</ol>
+<h2>Downloads</h2>
+
+<ol>
+<li><a href="{@docRoot}shareables/icon_templates-v1.0.zip">Android Icon
+Templates Pack, v1.0 »</a></li>
+</ol>
+
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
-<li><a href="{@docRoot}shareables/icon_templates-v1.0.zip">Android Icon
-Templates Pack, v1.0 »</a></li>
</ol>
diff --git a/docs/html/guide/practices/ui_guidelines/menu_design.jd b/docs/html/guide/practices/ui_guidelines/menu_design.jd
index ebf8a4b..840ee66 100644
--- a/docs/html/guide/practices/ui_guidelines/menu_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/menu_design.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Menu design quickview</h2>
+<h2>Quickview</h2>
<ul>
<li>An Options menu is for any commands that are global to the current activity. </li>
diff --git a/docs/html/guide/practices/ui_guidelines/widget_design.jd b/docs/html/guide/practices/ui_guidelines/widget_design.jd
index fc62fe6..e978069 100644
--- a/docs/html/guide/practices/ui_guidelines/widget_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/widget_design.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Widget design quickview</h2>
+<h2>Quickview</h2>
<ul>
<li>Widgets have six standard sizes on the Home screen</li>
@@ -27,7 +27,7 @@
<h2>See also</h2>
<ol>
-<li><a href="{@docRoot}guide/topics/appwidgets/index.html">AppWidgets</a> topic in the <em>Dev Guide</em></li>
+<li><a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a></li>
<li><a href="http://android-developers.blogspot.com/2009/04/introducing-home-screen-widgets-and.html">AppWidgets blog post</a></li>
</ol>
diff --git a/docs/html/guide/publishing/app-signing.jd b/docs/html/guide/publishing/app-signing.jd
index 34d9419..6758054 100644
--- a/docs/html/guide/publishing/app-signing.jd
+++ b/docs/html/guide/publishing/app-signing.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Signing quickview</h2>
+<h2>Quickview</h2>
<ul>
<li>All Android apps <em>must</em> be signed</a></li>
diff --git a/docs/html/guide/publishing/licensing.jd b/docs/html/guide/publishing/licensing.jd
index 07af68d..fc83ec0 100644
--- a/docs/html/guide/publishing/licensing.jd
+++ b/docs/html/guide/publishing/licensing.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>Market Licensing quickview: </h2>
+ <h2>Quickview</h2>
<ul>
<li>Licensing lets you protect your application on any device that includes Android Market.</li>
<li>Your app maintains control of how it enforces its licensing status. </li>
diff --git a/docs/html/guide/publishing/preparing.jd b/docs/html/guide/publishing/preparing.jd
index 442c12a..45a5b77 100644
--- a/docs/html/guide/publishing/preparing.jd
+++ b/docs/html/guide/publishing/preparing.jd
@@ -1,20 +1,6 @@
page.title=Preparing to Publish: A Checklist
@jd:body
-<!--
-<div id="qv-wrapper">
-<div id="qv">
-
-<h2>In this document</h2>
-
-<ol>
-<li><a href=""></a></li>
-</ol>
-
-</div>
-</div>
--->
-
<p>Publishing an application means testing it, packaging it appropriately, and
making it available to users of Android-powered mobile devices.</p>
@@ -34,7 +20,7 @@
<div class="special">
-<p>Before you consider your application ready for release:</p>
+<p><a href="#releaseready">Before you consider your application ready for release</a>:</p>
<ol>
<li>Test your application extensively on an actual device </li>
@@ -44,7 +30,7 @@
<li>Turn off logging and debugging and clean up data/files</li>
</ol>
-<p>Before you do the final compile of your application:</p>
+<p><a href="#finalcompile">Before you do the final compile of your application</a>:</p>
<ol start="6">
<li>Version your application</li>
@@ -52,8 +38,9 @@
<li>Register for a Maps API Key, if your application is using MapView elements</li>
</ol>
-<p><em>Compile your application...</em></p>
-<p>After compiling your application:</p>
+<p><a href="#compile">Compile your application</a></p>
+
+<p><a href="#post-compile">After you compile your application</a>:</p>
<ol start="9">
<li>Sign your application</li>
<li>Test your compiled application</li>
@@ -242,7 +229,7 @@
you can compile your application for release.</p>
-<h2 id="post-compile">After compiling your application</h2>
+<h2 id="post-compile">After you compile your application</h2>
<h3 id="signapp">9. Sign your application</h3>
diff --git a/docs/html/guide/publishing/publishing.jd b/docs/html/guide/publishing/publishing.jd
index 9b470c8..af1ea74 100644
--- a/docs/html/guide/publishing/publishing.jd
+++ b/docs/html/guide/publishing/publishing.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Publishing quickview</h2>
+<h2>Quickview</h2>
<ul>
<li>You can publish your application using a hosted service such as Android Market or through a web server.</li>
diff --git a/docs/html/guide/publishing/versioning.jd b/docs/html/guide/publishing/versioning.jd
index 1d55f8a..b646247 100644
--- a/docs/html/guide/publishing/versioning.jd
+++ b/docs/html/guide/publishing/versioning.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Versioning quickview</h2>
+<h2>Quickview</h2>
<ul>
<li>Your application <em>must</em> be versioned</a></li>
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index 7a8dd59..3de5627 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -3,12 +3,14 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>Key classes</h2>
- <ol>
- <li>{@link android.appwidget.AppWidgetProvider}</li>
- <li>{@link android.appwidget.AppWidgetProviderInfo}</li>
- <li>{@link android.appwidget.AppWidgetManager}</li>
- </ol>
+ <h2>Quickview</h2>
+ <ul>
+ <li>App Widgets provide users access to some of your application features
+directly from the Home screen (without the need to launch an activity)</li>
+ <li>App Widgets are backed by a special kind of broadcast receiver that handles the App
+Widget lifecycle</li>
+ </ul>
+
<h2>In this document</h2>
<ol>
<li><a href="#Basics">The Basics</a></li>
@@ -28,6 +30,13 @@
</li>
</ol>
+ <h2>Key classes</h2>
+ <ol>
+ <li>{@link android.appwidget.AppWidgetProvider}</li>
+ <li>{@link android.appwidget.AppWidgetProviderInfo}</li>
+ <li>{@link android.appwidget.AppWidgetManager}</li>
+ </ol>
+
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html">App Widget Design
diff --git a/docs/html/guide/topics/fundamentals.jd b/docs/html/guide/topics/fundamentals.jd
index db06efc..84c2ed2 100644
--- a/docs/html/guide/topics/fundamentals.jd
+++ b/docs/html/guide/topics/fundamentals.jd
@@ -3,14 +3,6 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Key classes</h2>
-<ol>
-<li>{@link android.app.Activity}</li>
-<li>{@link android.app.Service}</li>
-<li>{@link android.content.BroadcastReceiver}</li>
-<li>{@link android.content.ContentProvider}</li>
-<li>{@link android.content.Intent}</li>
-</ol>
<h2>In this document</h2>
<ol>
@@ -43,6 +35,16 @@
<li><a href="#proclife">Processes and lifecycles</a></li>
</ol></li>
</ol>
+
+<h2>Key classes</h2>
+<ol>
+<li>{@link android.app.Activity}</li>
+<li>{@link android.app.Service}</li>
+<li>{@link android.content.BroadcastReceiver}</li>
+<li>{@link android.content.ContentProvider}</li>
+<li>{@link android.content.Intent}</li>
+</ol>
+
</div>
</div>
diff --git a/docs/html/guide/topics/fundamentals/activities.jd b/docs/html/guide/topics/fundamentals/activities.jd
new file mode 100644
index 0000000..b616ab8
--- /dev/null
+++ b/docs/html/guide/topics/fundamentals/activities.jd
@@ -0,0 +1,762 @@
+page.title=Activities
+parent.title=Application Fundamentals
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Quickview</h2>
+<ul>
+ <li>An activity provides a user interface for a single screen in your application</li>
+ <li>Activities can move into the background and then be resumed with their state restored</li>
+</ul>
+
+<h2>In this document</h2>
+<ol>
+ <li><a href="#Creating">Creating an Activity</a>
+ <ol>
+ <li><a href="#UI">Implementing a user interface</a></li>
+ <li><a href="#Declaring">Declaring the activity in the manifest</a></li>
+ </ol>
+ </li>
+ <li><a href="#StartingAnActivity">Starting an Activity</a>
+ <ol>
+ <li><a href="#StartingAnActivityForResult">Starting an Activity for a Result</a></li>
+ </ol>
+ </li>
+ <li><a href="#Lifecycle">Managing the Activity Lifecycle</a>
+ <ol>
+ <li><a href="#ImplementingLifecycleCallbacks">Implementing the lifecycle callbacks</a></li>
+ <li><a href="#SavingActivityState">Saving activity state</a></li>
+ <li><a href="#ConfigurationChanges">Handling configuration changes</a></li>
+ <li><a href="#CoordinatingActivities">Coordinating activities</a></li>
+ </ol>
+ </li>
+</ol>
+
+<h2>Key classes</h2>
+<ol>
+ <li>{@link android.app.Activity}</li>
+</ol>
+
+<h2>See also</h2>
+<ol>
+ <li><a href="{@docRoot}resources/tutorials/hello-world.html">Hello World Tutorial</a></li>
+ <li><a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack">Tasks and Back
+Stack</a></li>
+</ol>
+
+</div>
+</div>
+
+
+
+<p>An {@link android.app.Activity} is an application component that provides a screen with which
+users can interact in order to do something, such as dial the phone, take a photo, send an email, or
+view a map. Each activity is given a window in which to draw its user interface. The window
+typically fills the screen, but may be smaller than the screen and float on top of other
+windows.</p>
+
+<p> An application usually consists of multiple activities that are loosely bound
+to each other. Typically, one activity in an application is specified as the "main" activity, which
+is presented to the user when launching the application for the first time. Each
+activity can then start another activity in order to perform different actions. Each time a new
+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
+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>
+
+<p>When an activity is stopped because a new activity starts, it is notified of this change in state
+through the activity's lifecycle callback methods.
+There are several callback methods that an activity might receive, due to a change in its
+state—whether the system is creating it, stopping it, resuming it, or destroying it—and
+each callback provides you the opportunity to perform specific work that's
+appropriate to that state change. For instance, when stopped, your activity should release any
+large objects, such as network or database connections. When the activity resumes, you can
+reacquire the necessary resources and resume actions that were interrupted. These state transitions
+are all part of the activity lifecycle.</p>
+
+<p>The rest of this document discusses the basics of how to build and use an activity,
+including a complete discussion of how the activity lifecycle works, so you can properly manage
+the transition between various activity states.</p>
+
+
+
+<h2 id="Creating">Creating an Activity</h2>
+
+<p>To create an activity, you must create a subclass of {@link android.app.Activity} (or
+an existing subclass of it). In your subclass, you need to implement callback methods that the
+system calls when the activity transitions between various states of its lifecycle, such as when
+the activity is being created, stopped, resumed, or destroyed. The two most important callback
+methods are:</p>
+
+<dl>
+ <dt>{@link android.app.Activity#onCreate onCreate()}</dt>
+ <dd>You must implement this method. The system calls this when creating your
+ activity. Within your implementation, you should initialize the essential components of your
+activity.
+ Most importantly, this is where you must call {@link android.app.Activity#setContentView
+ setContentView()} to define the layout for the activity's user interface.</dd>
+ <dt>{@link android.app.Activity#onPause onPause()}</dt>
+ <dd>The system calls this method as the first indication that the user is leaving your
+activity (though it does not always mean the activity is being destroyed). This is usually where you
+should commit any changes that should be persisted beyond the current user session (because
+the user might not come back).</dd>
+</dl>
+
+<p>There are several other lifecycle callback methods that you should use in order to provide a
+fluid user experience between activities and handle unexpected interuptions that cause your activity
+to be stopped and even destroyed. All of the lifecycle callback methods are discussed later, in
+the section about <a href="#Lifecycle">Managing the Activity Lifecycle</a>.</p>
+
+
+
+<h3 id="UI">Implementing a user interface</h3>
+
+<p> The user interface for an activity is provided by a hierarchy of views—objects derived
+from the {@link android.view.View} class. Each view controls a particular rectangular space
+within the activity's window and can respond to user interaction. For example, a view might be a
+button that initiates an action when the user touches it.</p>
+
+<p>Android provides a number of ready-made views that you can use to design and organize your
+layout. "Widgets" are views that provide a visual (and interactive) elements for the screen, such
+as a button, text field, checkbox, or just an image. "Layouts" are views derived from {@link
+android.view.ViewGroup} that provide a unique layout model for its child views, such as a linear
+layout, a grid layout, or relative layout. You can also subclass the {@link android.view.View} and
+{@link android.view.ViewGroup} classes (or existing subclasses) to create your own widgets and
+layouts and apply them to your activity layout.</p>
+
+<p>The most common way to define a layout using views is with an XML layout file saved in your
+application resources. This way, you can maintain the design of your user interface separately from
+the source code that defines the activity's behavior. You can set the layout as the UI for your
+activity with {@link android.app.Activity#setContentView(int) setContentView()}, passing the
+resource ID for the layout. However, you can also create new {@link android.view.View}s in your
+activity code and build a view hierarchy by inserting new {@link
+android.view.View}s into a {@link android.view.ViewGroup}, then use that layout by passing the root
+{@link android.view.ViewGroup} to {@link android.app.Activity#setContentView(View)
+setContentView()}.</p>
+
+<p>For information about creating a user interface, see the <a
+href="{@docRoot}guide/topics/ui/index.html">User Interface</a> documentation.</p>
+
+
+
+<h3 id="Declaring">Declaring the activity in the manifest</h3>
+
+<p>You must declare your activity in the manifest file in order for it to
+be accessible to the system. To decalare your activity, open your manifest file and add an <a
+href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element
+as a child of the <a
+href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
+element. For example:</p>
+
+<pre>
+<manifest ... >
+ <application ... >
+ <activity android:name=".ExampleActivity" />
+ ...
+ </application ... >
+ ...
+</manifest >
+</pre>
+
+<p>There are several other attributes that you can include in this element, to define properties
+such as the label for the activity, an icon for the activity, or a theme to style the activity's
+UI. See the <a
+href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element
+reference for more information about available attributes.</p>
+
+
+<h4>Using intent filters</h4>
+
+<p>An <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
+<activity>}</a> element can also specify various intent filters—using the <a
+href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
+<intent-filter>}</a> element—in order to declare how other application components may
+activate it.</p>
+
+<p>When you create a new application using the Android SDK tools, the stub activity
+that's created for you automatically includes an intent filter that declares the activity
+responds to the "main" action and should be placed in the "launcher" category. The intent filter
+looks like this:</p>
+
+<pre>
+<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+</activity>
+</pre>
+
+<p>The <a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
+<action>}</a> element specifies that this is the "main" entry point to the application. The <a
+href="{@docRoot}guide/topics/manifest/category-element.html">{@code
+<category>}</a> element specifies that this activity should be listed in the
+system's application launcher (to allow users to launch this activity).</p>
+
+<p>If you intend for your application to be self-contained and not allow other applications to
+activate its activities, then you don't need any other intent filters. Only one activity should
+have the "main" action and "launcher" category, as in the previous example. Activities that
+you don't want to make available to other applications should have no intent filters and you can
+start them yourself using explicit intents (as discussed in the following section).</p>
+
+<p>However, if you want your activity to respond to implicit intents that are delivered from
+other applications (and your own), then you must define additional intent filters for your
+activity. For each type of intent to which you want to respond, you must include an <a
+href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
+<intent-filter>}</a> that includes an
+<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
+<action>}</a> element and, optionally, a <a
+href="{@docRoot}guide/topics/manifest/category-element.html">{@code
+<category>}</a> element and/or a <a
+href="{@docRoot}guide/topics/manifest/data-element.html">{@code
+<data>}</a> element. These elements specify the type of intent to which your activity can
+respond.</p>
+
+<p>For more information about how your activities can respond to intents, see the <a
+href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
+document.</p>
+
+
+
+<h2 id="StartingAnActivity">Starting an Activity</h2>
+
+<p>You can start another activity by calling {@link android.app.Activity#startActivity
+ startActivity()}, passing it an {@link android.content.Intent} that describes the activity you
+ want to start. The intent specifies either the exact activity you want to start or describes the
+ type of action you want to perform (and the system selects the appropriate activity for you,
+which
+ can even be from a different application). An intent can also carry small amounts of data to be
+ used by the activity that is started.</p>
+
+<p>When working within your own application, you'll often need to simply launch a known activity.
+ You can do so by creating an intent that explicitly defines the activity you want to start,
+using the class name. For example, here's how one activity starts another activity named {@code
+SignInActivity}:</p>
+
+<pre>
+Intent intent = new Intent(this, SignInActivity.class);
+startActivity(intent);
+</pre>
+
+<p>However, your application might also want to perform some action, such as send an email, text
+ message, or status update, using data from your activity. In this case, your application might
+ not have its own activities to perform such actions, so you can instead leverage the activities
+ provided by other applications on the device, which can perform the actions for you. This is where
+intents are really valuable—you can create an intent that describes an action you want to
+perform and the system
+ launches the appropriate activity from another application. If there are
+ multiple activities that can handle the intent, then the user can select which one to use. For
+ example, if you want to allow the user to send an email message, you can create the
+ following intent:</p>
+
+<pre>
+Intent intent = new Intent(Intent.ACTION_SEND);
+intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
+startActivity(intent);
+</pre>
+
+<p>The {@link android.content.Intent#EXTRA_EMAIL} extra added to the intent is a string array of
+ email addresses to which the email should be sent. When an email application responds to this
+ intent, it reads the string array provided in the extra and places them in the "to" field of the
+ email composition form. In this situation, the email application's activity starts and when the
+ user is done, your activity resumes.</p>
+
+
+
+
+<h3 id="StartingAnActivityForResult">Starting an activity for a result</h3>
+
+<p>Sometimes, you might want to receive a result from the activity that you start. In that case,
+ start the activity by calling {@link android.app.Activity#startActivityForResult
+ startActivityForResult()} (instead of {@link android.app.Activity#startActivity
+ startActivity()}). To then receive the result from the subsequent
+activity, implement the {@link android.app.Activity#onActivityResult onActivityResult()} callback
+ method. When the subsequent activity is done, it returns a result in an {@link
+android.content.Intent} to your {@link android.app.Activity#onActivityResult onActivityResult()}
+method.</p>
+
+<p>For example, perhaps you want the user to pick one of their contacts, so your activity can
+do something with the information in that contact. Here's how you can create such an intent and
+handle the result:</p>
+
+<pre>
+private void pickContact() {
+ // Create an intent to "pick" a contact, as defined by the content provider URI
+ Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
+ startActivityForResult(intent, PICK_CONTACT_REQUEST);
+}
+
+@Override
+protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // If the request went well (OK) and the request was PICK_CONTACT_REQUEST
+ if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
+ // Perform a query to the contact's content provider for the contact's name
+ Cursor cursor = getContentResolver().query(data.getData(),
+ new String[] {Contacts.DISPLAY_NAME}, null, null, null);
+ if (cursor.moveToFirst()) { // True if the cursor is not empty
+ int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
+ String name = cursor.getString(columnIndex);
+ // Do something with the selected contact's name...
+ }
+ }
+}
+</pre>
+
+<p>This example shows the basic logic you should use in your {@link
+android.app.Activity#onActivityResult onActivityResult()} method in order to handle an
+activity result. The first condition checks whether the request was successful—if it was, then
+the {@code resultCode} will be {@link android.app.Activity#RESULT_OK}—and whether the request
+to which this result is responding is known—in this case, the {@code requestCode} matches the
+second parameter sent with {@link android.app.Activity#startActivityForResult
+startActivityForResult()}. From there, the code handles the activity result by querying the
+data returned in an {@link android.content.Intent} (the {@code data} parameter).</p>
+
+<p>What happens is, a {@link
+android.content.ContentResolver} performs a query against a content provider, which returns a
+{@link android.database.Cursor} that allows the queried data to be read. For more information, see
+the <a
+href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> document.</p>
+
+<p>For more information about using intents, see the <a
+href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent
+Filters</a> document.</p>
+
+
+<h2 id="ShuttingDown">Shutting Down an Activity</h2>
+
+<p>You can shut down an activity by calling its {@link android.app.Activity#finish
+finish()} method. You can also shut down a separate activity that you previously started by calling
+{@link android.app.Activity#finishActivity finishActivity()}.</p>
+
+<p class="note"><strong>Note:</strong> In most cases, you should not explicitly finish an activity
+using these methods. As discussed in the following section about the activity lifecycle, the
+Android system manages the life of an activity for you, so you do not need to finish your own
+activities. Calling these methods could adversely affect the expected user
+experience and should only be used when you absolutely do not want the user to return to this
+instance of the activity.</p>
+
+
+<h2 id="Lifecycle">Managing the Activity Lifecycle</h2>
+
+<p>Managing the lifecycle of your activities by implementing callback methods is
+crucial to developing a strong
+and flexible application. The lifecycle of an activity is directly affected by its association with
+other activities, its task and back stack.</p>
+
+<p>An activity can exist in essentially three states:</p>
+
+<dl>
+ <dt><i>Resumed</i></dt>
+ <dd>The activity is in the foreground of the screen and has user focus. (This state is
+also sometimes referred to as "running".)</dd>
+
+ <dt><i>Paused</i></dt>
+ <dd>Another activity is in the foreground and has focus, but this one is still visible. That is,
+another activity is visible on top of this one and that activity is partially transparent or doesn't
+cover the entire screen. A paused activity is completely alive (the {@link android.app.Activity}
+object is retained in memory, it maintains all state and member information, and remains attached to
+the window manager), but can be killed by the system in extremely low memory situations.</dd>
+
+ <dt><i>Stopped</i></dt>
+ <dd>The activity is completely obscured by another activity (the activity is now in the
+"background"). A stopped activity is also still alive (the {@link android.app.Activity}
+object is retained in memory, it maintains all state and member information, but is <em>not</em>
+attached to the window manager). However, it is no longer visible to the user and it
+can be killed by the system when memory is needed elsewhere.</dd>
+</dl>
+
+<p>If an activity is paused or stopped, the system can drop it from memory either by asking it to
+finish (calling its {@link android.app.Activity#finish finish()} method), or simply killing its
+process. When the activity is opened again (after being finished or killed), it must be created all
+over.</p>
+
+
+
+<h3 id="ImplementingLifecycleCallbacks">Implementing the lifecycle callbacks</h3>
+
+<p>When an activity transitions into and out of the different states described above, it is notified
+through various callback methods. All of the callback methods are hooks that you
+can override to do appropriate work when the state of your activity changes. The following skeleton
+activity includes each of the fundamental lifecycle methods:</p>
+
+
+<pre>
+public class ExampleActivity extends Activity {
+ @Override
+ public void {@link android.app.Activity#onCreate onCreate}(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // The activity is being created.
+ }
+ @Override
+ protected void {@link android.app.Activity#onStart onStart()} {
+ super.onStart();
+ // The activity is about to become visible.
+ }
+ @Override
+ protected void {@link android.app.Activity#onResume onResume()} {
+ super.onResume();
+ // The activity has become visible (it is now "resumed").
+ }
+ @Override
+ protected void {@link android.app.Activity#onPause onPause()} {
+ super.onPause();
+ // Another activity is taking focus (this activity is about to be "paused").
+ }
+ @Override
+ protected void {@link android.app.Activity#onStop onStop()} {
+ super.onStop();
+ // The activity is no longer visible (it is now "stopped")
+ }
+ @Override
+ protected void {@link android.app.Activity#onDestroy onDestroy()} {
+ super.onDestroy();
+ // The activity is about to be destroyed.
+ }
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> Your implementation of these lifecycle methods must
+always call the superclass implementation before doing any work, as shown in the examples above.</p>
+
+<p>Taken together, these methods define the entire lifecycle of an activity. By implementing these
+methods, you can monitor three nested loops in the activity lifecycle: </p>
+
+<ul>
+<li>The <b>entire lifetime</b> of an activity happens between the call to {@link
+android.app.Activity#onCreate onCreate()} and the call to {@link
+android.app.Activity#onDestroy}. Your activity should perform setup of
+"global" state (such as defining layout) in {@link android.app.Activity#onCreate onCreate()}, and
+release all remaining resources in {@link android.app.Activity#onDestroy}. For example, if your
+activity has a thread running in the background to download data from the network, it might create
+that thread in {@link android.app.Activity#onCreate onCreate()} and then stop the thread in {@link
+android.app.Activity#onDestroy}.</li>
+
+<li><p>The <b>visible lifetime</b> of an activity happens between the call to {@link
+android.app.Activity#onStart onStart()} and the call to {@link
+android.app.Activity#onStop onStop()}. During this time, the user can see the activity
+on-screen and interact with it. For example, {@link android.app.Activity#onStop onStop()} is called
+when a new activity starts and this one is no longer visible. Between these two methods, you can
+maintain resources that are needed to show the activity to the user. For example, you can register a
+{@link android.content.BroadcastReceiver} in {@link
+android.app.Activity#onStart onStart()} to monitor changes that impact your UI, and unregister
+it in {@link android.app.Activity#onStop onStop()} when the user can no longer see what you are
+displaying. The system might call {@link android.app.Activity#onStart onStart()} and {@link
+android.app.Activity#onStop onStop()} multiple times during the entire lifetime of the activity, as
+the activity alternates between being visible and hidden to the user.</p></li>
+
+<li><p>The <b>foreground lifetime</b> of an activity happens between the call to {@link
+android.app.Activity#onResume onResume()} and the call to {@link android.app.Activity#onPause
+onPause()}. During this time, the activity is in front of all other activities on screen and has
+user input focus. An activity can frequently transition in and out of the foreground—for
+example, {@link android.app.Activity#onPause onPause()} is called when the device goes to sleep or
+when a dialog appears. Because this state can transition often, the code in these two methods should
+be fairly lightweight in order to avoid slow transitions that make the user wait.</p></li>
+</ul>
+
+<p>Figure 1 illustrates these loops and the paths an activity might take between states.
+The rectangles represent the callback methods you can implement to perform operations when
+the activity transitions between states. <p>
+
+<img src="{@docRoot}images/activity_lifecycle.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> The activity lifecycle.</p>
+
+<p>The same lifecycle callback methods are listed in table 1, which describes each of the callback
+methods in more detail and locates each one within the
+activity's overall lifecycle, including whether the system can kill the activity after the
+callback method completes.</p>
+
+<p class="table-caption"><strong>Table 1.</strong> A summary of the activity lifecycle's
+callback methods.</p>
+
+<table border="2" width="85%" frame="hsides" rules="rows">
+<colgroup align="left" span="3"></colgroup>
+<colgroup align="left"></colgroup>
+<colgroup align="center"></colgroup>
+<colgroup align="center"></colgroup>
+
+<thead>
+<tr><th colspan="3">Method</th> <th>Description</th> <th>Killable after?</th> <th>Next</th></tr>
+</thead>
+
+<tbody>
+<tr>
+ <td colspan="3" align="left"><code>{@link android.app.Activity#onCreate onCreate()}</code></td>
+ <td>Called when the activity is first created.
+ This is where you should do all of your normal static set up —
+ create views, bind data to lists, and so on. This method is passed
+ a Bundle object containing the activity's previous state, if that
+ state was captured (see <a href="#actstate">Saving Activity State</a>,
+ later).
+ <p>Always followed by {@code onStart()}.</p></td>
+ <td align="center">No</td>
+ <td align="center">{@code onStart()}</td>
+</tr>
+
+<tr>
+ <td rowspan="5" style="border-left: none; border-right: none;"> </td>
+ <td colspan="2" align="left"><code>{@link android.app.Activity#onRestart
+onRestart()}</code></td>
+ <td>Called after the activity has been stopped, just prior to it being
+ started again.
+ <p>Always followed by {@code onStart()}</p></td>
+ <td align="center">No</td>
+ <td align="center">{@code onStart()}</td>
+</tr>
+
+<tr>
+ <td colspan="2" align="left"><code>{@link android.app.Activity#onStart onStart()}</code></td>
+ <td>Called just before the activity becomes visible to the user.
+ <p>Followed by {@code onResume()} if the activity comes
+ to the foreground, or {@code onStop()} if it becomes hidden.</p></td>
+ <td align="center">No</td>
+ <td align="center">{@code onResume()} <br/>or<br/> {@code onStop()}</td>
+</tr>
+
+<tr>
+ <td rowspan="2" style="border-left: none;"> </td>
+ <td align="left"><code>{@link android.app.Activity#onResume onResume()}</code></td>
+ <td>Called just before the activity starts
+ interacting with the user. At this point the activity is at
+ the top of the activity stack, with user input going to it.
+ <p>Always followed by {@code onPause()}.</p></td>
+ <td align="center">No</td>
+ <td align="center">{@code onPause()}</td>
+</tr>
+
+<tr>
+ <td align="left"><code>{@link android.app.Activity#onPause onPause()}</code></td>
+ <td>Called when the system is about to start resuming another
+ activity. This method is typically used to commit unsaved changes to
+ persistent data, stop animations and other things that may be consuming
+ CPU, and so on. It should do whatever it does very quickly, because
+ the next activity will not be resumed until it returns.
+ <p>Followed either by {@code onResume()} if the activity
+ returns back to the front, or by {@code onStop()} if it becomes
+ invisible to the user.</td>
+ <td align="center"><strong style="color:#800000">Yes</strong></td>
+ <td align="center">{@code onResume()} <br/>or<br/> {@code onStop()}</td>
+</tr>
+
+<tr>
+ <td colspan="2" align="left"><code>{@link android.app.Activity#onStop onStop()}</code></td>
+ <td>Called when the activity is no longer visible to the user. This
+ may happen because it is being destroyed, or because another activity
+ (either an existing one or a new one) has been resumed and is covering it.
+ <p>Followed either by {@code onRestart()} if
+ the activity is coming back to interact with the user, or by
+ {@code onDestroy()} if this activity is going away.</p></td>
+ <td align="center"><strong style="color:#800000">Yes</strong></td>
+ <td align="center">{@code onRestart()} <br/>or<br/> {@code onDestroy()}</td>
+</tr>
+
+<tr>
+ <td colspan="3" align="left"><code>{@link android.app.Activity#onDestroy
+onDestroy()}</code></td>
+ <td>Called before the activity is destroyed. This is the final call
+ that the activity will receive. It could be called either because the
+ activity is finishing (someone called <code>{@link android.app.Activity#finish
+ finish()}</code> on it), or because the system is temporarily destroying this
+ instance of the activity to save space. You can distinguish
+ between these two scenarios with the <code>{@link
+ android.app.Activity#isFinishing isFinishing()}</code> method.</td>
+ <td align="center"><strong style="color:#800000">Yes</strong></td>
+ <td align="center"><em>nothing</em></td>
+</tr>
+</tbody>
+</table>
+
+<p>The column labeled "Killable after?" indicates whether or not the system can
+kill the process hosting the activity at any time <em>after the method returns</em>, without
+executing another line of the activity's code. Three methods are marked "yes": ({@link
+android.app.Activity#onPause
+onPause()}, {@link android.app.Activity#onStop onStop()}, and {@link android.app.Activity#onDestroy
+onDestroy()}). Because {@link android.app.Activity#onPause onPause()} is the first
+of the three, once the activity is created, {@link android.app.Activity#onPause onPause()} is the
+last method that's guaranteed to be called before the process <em>can</em> be killed—if
+the system must recover memory in an emergency, then {@link
+android.app.Activity#onStop onStop()} and {@link android.app.Activity#onDestroy onDestroy()} might
+not be called. Therefore, you should use {@link android.app.Activity#onPause onPause()} to write
+crucial persistent data (such as user edits) to storage. However, you should be selective about
+what information must be retained during {@link android.app.Activity#onPause onPause()}, because any
+blocking procedures in this method block the transition to the next activity and slow the user
+experience.</p>
+
+<p> Methods that are marked "No" in the <b>Killable</b> column protect the process hosting the
+activity from being killed from the moment they are called. Thus, an activity is killable
+from the time {@link android.app.Activity#onPause onPause()} returns to the time
+{@link android.app.Activity#onResume onResume()} is called. It will not again be killable until
+{@link android.app.Activity#onPause onPause()} is again called and returns. </p>
+
+<p class="note"><strong>Note:</strong> An activity that's not technically "killable" by this
+definition in table 1 might still be killed by the system—but that would happen only in
+extreme circumstances when there is no other recourse. When an activity might be killed is
+discussed more in the <a
+href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html">Processes and
+Threading</a> document.</p>
+
+
+<h3 id="SavingActivityState">Saving activity state</h3>
+
+<p>The introduction to <a href="Lifecycle">Managing the Activity Lifecycle</a> briefly mentions that
+when an activity is paused or stopped, the state of the activity is retained. This is true because
+the {@link android.app.Activity} object is still held in memory when it is paused or
+stopped—all information about its members and current state is still alive. Thus, any changes
+the user made within the activity are retained in memory, so that when the activity returns to the
+foreground (when it "resumes"), those changes are still there.</p>
+
+<div class="figure" style="width:615px">
+<img src="{@docRoot}images/fundamentals/restore_instance.png" alt="" />
+<p class="img-caption"><strong>Figure 2.</strong> The two ways in which an activity returns to user
+focus with its state intact: either the activity is stopped, then resumed and the activity state
+remains intact (left), or the activity is destroyed, then recreated and the activity must restore
+the previous activity state (right).</p>
+</div>
+
+<p>However, when the system destroys an activity in order to recover memory, the {@link
+android.app.Activity} object is destroyed, so the system cannot simply resume it with its state
+intact. Instead, the system must recreate the {@link android.app.Activity} object if the user
+navigates back to it. Yet, the user is unaware
+that the system destroyed the activity and recreated it and, thus, probably
+expects the activity to be exactly as it was. In this situation, you can ensure that
+important information about the activity state is preserved by implementing an additional
+callback method that allows you to save information about the state of your activity and then
+restore it when the the system recreates the activity.</p>
+
+<p>The callback method in which you can save information about the current state of your activity is
+{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}. The system calls this method
+before making the activity vulnerable to being destroyed and passes it
+a {@link android.os.Bundle} object. The {@link android.os.Bundle} is where you can store
+state information about the activity as name-value pairs, using methods such as {@link
+android.os.Bundle#putString putString()}. Then, if the system kills your activity's
+process and the user navigates back to your activity, the system passes the {@link
+android.os.Bundle} to {@link android.app.Activity#onCreate onCreate()} so you can restore the
+activity state you saved during {@link android.app.Activity#onSaveInstanceState
+onSaveInstanceState()}. If there is no state information to restore, then the {@link
+android.os.Bundle} passed to {@link android.app.Activity#onCreate onCreate()} is null.</p>
+
+<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
+closing the activity). If the method is called, it is always called before {@link
+android.app.Activity#onStop onStop()} and possibly before {@link android.app.Activity#onPause
+onPause()}.</p>
+
+<p>However, even if you do nothing and do not implement {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()}, some of the activity state is
+restored by the {@link android.app.Activity} class's default implementation of {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()}. Specifically, the default
+implementation calls {@link
+android.view.View#onSaveInstanceState onSaveInstanceState()} for every {@link android.view.View}
+in the layout, which allows each view to provide information about itself
+that should be saved. Almost every widget in the Android framework implements this method as
+appropriate, such that any visible changes to the UI are automatically saved and restored when your
+activity is recreated. For example, the {@link android.widget.EditText} widget saves any text
+entered by the user and the {@link android.widget.CheckBox} widget saves whether it's checked or
+not. The only work required by you is to provide a unique ID (with the <a
+href="{@docRoot}guide/topics/resources/layout-resource.html#idvalue">{@code android:id}</a>
+attribute) for each widget you want to save its state. If a widget does not have an ID, then it
+cannot save its state.</p>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<p>You can also explicitly stop a view in your layout from saving its state by setting the
+{@link android.R.attr#saveEnabled android:saveEnabled} attribute to {@code "false"} or by calling
+the {@link android.view.View#setSaveEnabled setSaveEnabled()} method. Usually, you should not
+disable this, but you might if you want to restore the state of the activity UI differently.</p>
+</div>
+</div>
+
+<p>Although the default implementation of {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()} saves useful information about
+your activity's UI, you still might need to override it to save additional information.
+For example, you might need to save member values that changed during the activity's life (which
+might correlate to values restored in the UI, but the members that hold those UI values are not
+restored, by default).</p>
+
+<p>Because the default implementation of {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()} helps save the state of the UI, if
+you override the method in order to save additional state information, you should always call the
+superclass implementation of {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
+before doing any work.</p>
+
+<p class="note"><strong>Note:</strong> Because {@link android.app.Activity#onSaveInstanceState
+onSaveInstanceState()} is not guaranteed
+to be called, you should use it only to record the transient state of the activity (the state of
+the UI)—you should never use it to store persistent data. Instead, you should use {@link
+android.app.Activity#onPause onPause()} to store persistent data (such as data that should be saved
+to a database) when the user leaves the activity.</p>
+
+<p>A good way to test your application's ability to restore its state is to simply rotate the
+device so that the screen orientation changes. When the screen orientation changes, the system
+destroys and recreates the activity in order to apply alternative resources that might be available
+for the new orientation. For this reason alone, it's very important that your activity
+completely restores its state when it is recreated, because users regularly rotate the screen while
+using applications.</p>
+
+
+<h3 id="ConfigurationChanges">Handling configuration changes</h3>
+
+<p>Some device configurations can change during runtime (such as screen orientation, keyboard
+availability, and language). When such a change occurs, Android restarts the running Activity
+({@link android.app.Activity#onDestroy} is called, followed immediately by {@link
+android.app.Activity#onCreate onCreate()}). The restart behavior is
+designed to help your application adapt to new configurations by automatically reloading your
+application with alternative resources that you've provided. If you design your activity to
+properly handle this event, it will be more resilient to unexpected events in the activity
+lifecycle.</p>
+
+<p>The best way to handle a configuration change, such as a change in the screen orientation, is
+ to simply preserve the state of your application using {@link
+ android.app.Activity#onSaveInstanceState onSaveInstanceState()} and {@link
+android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} (or {@link
+android.app.Activity#onCreate onCreate()}), as discussed in the previous section.</p>
+
+<p>For a detailed discussion about configuration changes that happen at runtime and how you should
+handle them, read <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling
+Runtime Changes</a>.</p>
+
+
+
+<h3 id="CoordinatingActivities">Coordinating activities</h3>
+
+ <p>When one activity starts another, they both experience lifecycle transitions. The first activity
+pauses and stops (though, it won't stop if it's still visible in the background), while the other
+activity is created. In case these activities share data saved to disc or elsewhere, it's important
+to understand that the first activity is not completely stopped before the second one is created.
+Rather, the process of starting the second one overlaps with the process of stopping the first
+one.</p>
+
+<p>The order of lifecycle callbacks is well defined, particularly when the two activities are in the
+same process and one is starting the other. Here's the order of operations that occur when Activity
+A starts Acivity B: </p>
+
+<ol>
+<li>Activity A's {@link android.app.Activity#onPause onPause()} method executes.</li>
+
+<li>Activity B's {@link android.app.Activity#onCreate onCreate()}, {@link
+android.app.Activity#onStart onStart()}, and {@link android.app.Activity#onResume onResume()}
+methods execute in sequence. (Activity B now has user focus.)</li>
+
+<li>Then, if Activity A is no longer visible on screen, its {@link
+android.app.Activity#onStop onStop()} method executes.</li>
+</ol>
+
+ <p>This predictable sequence of lifecycle callbacks allows you to manage the transition of
+information from one activity to another. For example, if you must write to a database when the
+first activity stops so that the following activity can read it, then you should write to the
+database during {@link android.app.Activity#onPause onPause()} instead of during {@link
+android.app.Activity#onStop onStop()}.</p>
+
+
+<h2>Beginner's Path</h2>
+
+<p>For more information about how Android maintains a history of activities and
+enables user multitasking, continue with the <b><a
+href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
+Stack</a></b> document.</p>
diff --git a/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd b/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd
new file mode 100644
index 0000000..47dc5471
--- /dev/null
+++ b/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd
@@ -0,0 +1,568 @@
+page.title=Tasks and Back Stack
+parent.title=Application Fundamentals
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Quickview</h2>
+<ul>
+ <li>All activities belong to a task</li>
+ <li>A task contains a collection of activities in the order in which the user interacts with
+them</li>
+ <li>Tasks can move to the background and retain the state of each activity in order for the user
+to perform other tasks without loosing their work</li>
+</ul>
+
+<h2>In this document</h2>
+<ol>
+<li><a href="#ActivityState">Saving Activity State</a></li></li>
+<li><a href="#ManagingTasks">Managing Tasks</a>
+ <ol>
+ <li><a href="#TaskLaunchModes">Defining launch modes</a></li>
+ <li><a href="#Affinities">Handling affinities</a></li>
+ <li><a href="#Clearing">Clearing the back stack</a></li>
+ <li><a href="#Starting">Starting a task</a></li>
+ </ol>
+</li>
+</ol>
+
+<h2>See also</h2>
+<ol>
+ <li><a><a href="{@docRoot}videos/index.html#v=fL6gSd4ugSI">Application Lifecycle video</a></li>
+ <li><a
+href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>} manifest
+element</a></li>
+</ol>
+</div>
+</div>
+
+
+<p>An application usually contains multiple <a
+href="{@docRoot}guide/topics/fundamentals/activities.html">activities</a>. Each activity
+should be designed around a specific kind of action the user can perform and can start other
+activities. For example, an email application might have one activity to show a list of new email.
+When the user selects an email, a new activity opens to view that email.</p>
+
+<p>An activity can even start activities that exist in other applications on the device. For
+example, if your application wants to send an email, you can define an intent to perform a "send"
+action and include some data, such as an email address and a message. An activity from another
+application that declares itself to handle this kind of intent then opens. In this case, the intent
+is to send an email, so an email application's "compose" activity starts (if multiple activities
+support the same intent, then the system lets the user select which one to use). When the email is
+sent, your activity resumes and it seems as if the email activity was part of your application. Even
+though the activities may be from different applications, Android maintains this seamless user
+experience by keeping both activities in the same <em>task</em>.</p>
+
+<p>A task is a collection of activities that users interact with
+when performing a certain job. The activities are arranged in a stack (the "back stack"), in the
+order in which each activity is opened.</p>
+
+<!-- SAVE FOR WHEN THE FRAGMENT DOC IS ADDED
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h3>Adding fragments to a task's back stack</h3>
+
+<p>Your activity can also include {@link android.app.Fragment}s to the back stack. For example,
+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 key.</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
+C.</p>
+<p>For more information about using fragments and adding them to the back stack, see the {@link
+android.app.Fragment} class documentation.</p>
+
+</div>
+</div>
+-->
+
+<p>The device Home screen is the starting place for most tasks. When the user touches an icon in the
+application
+launcher (or a shortcut on the Home screen), that application's task comes to the foreground. If no
+task exists for the application (the application has not been used recently), then a new task
+is created and the "main" activity for that application opens as the root activity in the stack.</p>
+
+<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
+key, 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 key. 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 key, 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
+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>
+
+<div class="figure" style="width:369px">
+<img src="{@docRoot}images/fundamentals/diagram_multitasking.png" alt="" /> <p
+class="img-caption"><strong>Figure 2.</strong> Two tasks: Task A is in the background, waiting
+to be resumed, while Task B receives user interaction in the foreground.</p>
+</div>
+<div class="figure" style="width:178px">
+ <img src="{@docRoot}images/fundamentals/diagram_multiple_instances.png" alt="" /> <p
+class="img-caption"><strong>Figure 3.</strong> A single activity is instantiated multiple times.</p>
+</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 key. 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 key, 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
+that application, the user returns Home again and selects the application that originally
+started Task A. Now, Task A comes to the
+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 key 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.
+However, if the user is running many background tasks at the same time, the system might begin
+destroying background activities in order to recover memory, causing the activity states to be lost.
+See the following section about <a href="#ActivityState">Activity state</a>.</p>
+
+<p>Because the activities in the back stack are never rearranged, if your application allows
+users to start a particular activity from more than one activity, a new instance of
+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 key, 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>
+
+
+<p>To summarize the default behavior for activities and tasks:</p>
+
+<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 key while in Activity B, Activity A resumes with its state
+restored.</li>
+ <li>When the user leaves a task by pressing the HOME key, 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 key, 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>
+</ul>
+
+
+<h2 id="ActivityState">Saving Activity State</h2>
+
+<p>As discussed above, the system's default behavior preserves the state of an activity when it is
+stopped. This way, when users navigate back to a previous activity, its user interface appears
+the way they left it. However, you can—and <strong>should</strong>—proactively retain
+the state of your activities using callback methods, in case the activity is destroyed and must
+be recreated.</p>
+
+<p>When the system stops one of your activities (such as when a new activity starts or the task
+moves to the background), the system might destroy that activity completely if it needs to recover
+system memory. When this happens, information about the activity state is lost. If this happens, the
+system still
+knows that the activity has a place in the back stack, but when the activity is brought to the
+top of the stack the system must recreate it (rather than resume it). In order to
+avoid loosing the user's work, you should proactively retain it by implementing the {@link
+android.app.Activity#onSaveInstanceState onSaveInstanceState()} callback
+methods in your activity.</p>
+
+<p>For more information about how to save your activity state, see the <a
+href="{@docRoot}guide/topics/fundamentals/activities.html#SavingActivityState">Activities</a>
+document.</p>
+
+
+
+<h2 id="ManagingTasks">Managing Tasks</h2>
+
+<p>The way Android manages tasks and the back stack, as described above—by placing all
+activities started in succession in the same task and in a "last in, first out" stack—works
+great for most applications and you shouldn't have to worry about how your activities are associated
+with tasks or how they exist in the back stack. However, you might decide that you want to interrupt
+the normal behavior. Perhaps you want an activity in your application to begin a new task when it is
+started (instead of being placed within the current task); or, when you start an activity, you want
+to bring forward an existing instance of it (instead of creating a new
+instance on top of the back stack); or, you want your back stack to be cleared of all
+activitiesstart an activity except for the root activity when the user leaves the task.</p>
+
+<p>You can do these things and more, with attributes in the
+<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
+<activity>}</a> manifest element and with flags in the intent that you pass to {@link
+android.app.Activity#startActivity startActivity()}.</p>
+
+<p>In this regard, the the principal <a
+href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a>
+attributes you can use are:</p>
+
+<ul class="nolist">
+ <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code
+taskAffinity}</a></li>
+ <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
+launchMode}</a></li>
+ <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">{@code
+allowTaskReparenting}</a></li>
+ <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">{@code
+clearTaskOnLaunch}</a></li>
+ <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#always">{@code
+alwaysRetainTaskState}</a></li>
+ <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code
+finishOnTaskLaunch}</a></li>
+</ul>
+
+<p>And the principal intent flags you can use are:</p>
+
+<ul class="nolist">
+ <li>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</li>
+ <li>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</li>
+ <li>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</li>
+</ul>
+
+<p>In the following sections, you'll see how you can use these manifest attributes and intent
+flags to define how activities are associated with tasks and how the behave in the back stack.</p>
+
+
+<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 key. Be sure
+to test for navigation behaviors that might conflict with the user's expected behavior.</p>
+
+
+<h3 id="TaskLaunchModes">Defining launch modes</h3>
+
+<p>Launch modes allow you to define how a new instance of an activity is associated with the
+current task. You can define different launch modes in two ways:</p>
+<ul class="nolist">
+ <li><a href="#ManifestForTasks">Using the manifest file</a>
+ <p>When you declare an activity in your manifest file, you can specify how the activity
+should associate with tasks when it starts.</li>
+ <li><a href="#IntentFlagsForTasks">Using Intent flags</a>
+ <p>When you call {@link android.app.Activity#startActivity startActivity()},
+you can include a flag in the {@link android.content.Intent} that declares how (or
+whether) the new activity should associate with the current task.</p></li>
+</ul>
+
+<p>As such, if Activity A starts Activity B, Activity B can define in its manifest how it
+should associate with the current task (if at all) and Activity A can also request how Activity
+B should associate with current task. If both activities define how Activity B
+should associate with a task, then Activity A's request (as defined in the intent) is honored
+over Activity B's request (as defined in its manifest).</p>
+
+<p class="note"><strong>Note:</strong> Some the launch modes available in the manifest
+are not available as flags for an intent and, likewise, some launch modes available as flags
+for an intent cannot be defined in the manifest.</p>
+
+
+<h4 id="ManifestForTasks">Using the manifest file</h4>
+
+<p>When declaring an activity in your manifest file, you can specify how the activity should
+associate with a task using the <a
+href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a>
+element's <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
+launchMode}</a> attribute.</p>
+
+<p>The <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
+launchMode}</a> attribute specifies an instruction on how the activity should be launched into a
+task. There are four different launch modes you can assign to the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launchMode</a></code>
+attribute:</p>
+
+<dl>
+<dt>{@code "standard"} (the default mode)</dt>
+ <dd>Default. The system creates a new instance of the activity in the task from
+which it was started and routes the intent to it. The activity can be instantiated multiple times,
+each instance can belong to different tasks, and one task can have multiple instances.</dd>
+<dt>{@code "singleTop"}</dt>
+ <dd>If an instance of the activity already exists at the top of the current task, the system
+routes the intent to that instance through a call to its {@link
+android.app.Activity#onNewIntent onNewIntent()} method, rather than creating a new instance of the
+activity. The activity can be instantiated multiple times, each instance can
+belong to different tasks, and one task can have multiple instances (but only if the the
+activity at the top of the back stack is <em>not</em> an existing instance of the activity).
+ <p>For example, suppose a task's back stack consists of root activity A with activities B, C,
+and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D.
+If D has the default {@code "standard"} launch mode, a new instance of the class is launched and the
+stack becomes A-B-C-D-D. However, if D's launch mode is {@code "singleTop"}, the existing instance
+of D is deliverd the intent through {@link
+android.app.Activity#onNewIntent onNewIntent()}, because it's at the top of the stack—the
+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 key to return to the previous activity. But when an existing instance of
+an activity handles a new intent, the user cannot press the BACK key to return to the state of
+the activity before the new intent arrived in {@link android.app.Activity#onNewIntent
+onNewIntent()}.</p>
+</dd>
+
+<dt>{@code "singleTask"}</dt>
+ <dd>The system creates a new task and instantiates the activity at the root of the new task.
+However, if an instance of the activity already exists in a separate task, the system routes the
+intent to the existing instance through a call to its {@link
+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 key 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;
+any activities started by this one open in a separate task.</dd>
+</dl>
+
+
+<p>As another example, the Android Browser application declares that the web browser activity should
+always open in its own task—by specifying the {@code singleTask} launch mode in the <a
+href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element.
+This means that if your application issues an
+intent to open the Android Browser, its activity is <em>not</em> placed in the same
+task as your application. Instead, either a new task starts for the Browser or, if the Browser
+already has a task running in the background, that task is brought forward to handle the new
+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 key always takes the user to the previous activity. However, if you
+start an activity from your task (Task A) that specifies the {@code singleTask} launch mode, then
+that activity might have an instance in the background that belongs to a task with its own back
+stack (Task B). In this
+case, when Task B is brought forward to handle a new intent, the BACK key first navigates
+backward through the activities in Task B before returning to
+the top-most activity in Task A. Figure 4 visualizes this type of scenario.</p>
+
+<img src="{@docRoot}images/fundamentals/diagram_backstack_singletask_multiactivity.png" alt="" />
+<p class="img-caption"><strong>Figure 4.</strong> A representation of how an activity with
+launch mode "singleTask" is added to the back stack. If the activity is already a part of a
+background task with its own back stack (Task B), then the entire back stack also comes
+forward, on top of the current task (Task A).</p>
+
+<p>For more information about using launch modes in the manifest file, see the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
+element documentation, where the {@code launchMode} attribute and the accepted values are
+discussed more.</p>
+
+<p class="note"><strong>Note:</strong> The behaviors that you specify for your activity with the <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> attribute
+can be overriden by flags included with the intent that start your activity, as discussed in the
+next section.</p>
+
+
+
+<h4 id="#IntentFlagsForTasks">Using Intent flags</h4>
+
+<p>When starting an activity, you can modify the default association of an activity to its task
+by including flags in the intent that you deliver to {@link
+android.app.Activity#startActivity startActivity()}. The flags you can use to modify the
+default behavior are:</p>
+
+<p>
+ <dt>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</dt>
+ <dd>Start the activity in a new task. If a task is already running for the activity you are now
+starting, that task is brought to the foreground with its last state restored and the activity
+receives the new intent in {@link android.app.Activity#onNewIntent onNewIntent()}.
+ <p>This produces the same behavior as the {@code "singleTask"} <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> value,
+discussed in the previous section.</p></dd>
+ <dt>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</dt>
+ <dd>If the activity being started is the current activity (at the top of the back stack), then
+the existing instance receives a call to {@link android.app.Activity#onNewIntent onNewIntent()},
+instead of creating a new instance of the activity.
+ <p>This produces the same behavior as the {@code "singleTop"} <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> value,
+discussed in the previous section.</p></dd>
+ <dt>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</dt>
+ <dd>If the activity being started is already running in the current task, then instead
+of launching a new instance of that activity, all of the other activities on top of it are
+destroyed and this intent is delivered to the resumed instance of the activity (now on top),
+through {@link android.app.Activity#onNewIntent onNewIntent()}).
+ <p>There is no value for the <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
+attribute that produces this behavior.</p>
+ <p>{@code FLAG_ACTIVITY_CLEAR_TOP} is most often used in conjunction with {@code
+FLAG_ACTIVITY_NEW_TASK}. When used together, these flags are a way of locating an existing activity
+in another task and putting it in a position where it can respond to the intent. </p>
+ <p class="note"><strong>Note:</strong> If the launch mode of the designated activity is {@code
+"standard"}, it too is removed from the stack and a new instance is launched in its place to handle
+the incoming intent. That's because a new instance is always created for a new intent when the
+launch mode is {@code "standard"}. </p>
+</dd>
+</dl>
+
+
+
+
+
+<h3 id="Affinities">Handling affinities</h3>
+
+<p>The <em>affinity</em> indicates which task an activity prefers to belong to. By default, all the
+activities from the same application have an affinity for each other. So, by default, all
+activities in the same application prefer to be in the same task. However, you can modify
+the default affinity for an activity. Activities defined in
+different applications can share an affinity, or activities defined in the same application can be
+assigned different task affinities.</p>
+
+<p>You can modify the affinity for any given activity with the <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> attribute
+of the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a>
+element.</p>
+
+<p>The <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
+attribute takes a string value, which must be unique from the default package name
+declared in the <a href="{@docRoot}guide/topics/manifest/manifest-element.html">{@code
+<manifest>}</a> element, because the system uses that name to identify the default task
+affinity for the application.</p>
+
+<p>The affinity comes into play in two circumstances:</p>
+<ul>
+ <li>When the intent that launches an activity contains the {@link
+android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag.
+
+<p>A new activity is, by default, launched into the task of the activity
+that called {@link android.app.Activity#startActivity startActivity()}. It's pushed onto the same
+back stack as the caller. However, if the intent passed to {@link
+android.app.Activity#startActivity startActivity()} contains the {@link
+android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
+flag, the system looks for a different task to house the new activity. Often, it's a new task.
+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 key 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
+android.app.Activity#startActivity startActivity()}. If you have an activity that can be invoked by
+an external entity that might use this flag, take care that the user has a independent way to get
+back to the task that's started, such as with a launcher icon (the root activity of the task
+has a {@link android.content.Intent#CATEGORY_LAUNCHER} intent filter; see the <a
+href="#Starting">Starting a task</a> section below).</p>
+</li>
+
+ <li>When an activity has its <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">{@code
+allowTaskReparenting}</a> attribute set to {@code "true"}.
+ <p>In this case, the activity can move from the task it starts to the task it has an affinity
+for, when that task comes to the foreground.</p>
+ <p>For example, suppose that an activity that reports weather conditions in selected cities is
+defined as part of a travel application. It has the same affinity as other activities in the same
+application (the default application affinity) and it allows re-parenting with this attribute.
+When one of your activities starts the weather reporter activity, it initially belongs to the same
+task as your activity. However, when the travel application's task comes to the foreground, the
+weather reporter activity is reassigned to that task and displayed within it.</p>
+</li>
+</ul>
+
+<p class="note"><strong>Tip:</strong> If an {@code .apk} file contains more than one "application"
+from the user's point of view, you probably want to use the <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
+attribute to assign different affinities to the activities associated with each "application".</p>
+
+
+
+<h3 id="Clearing">Clearing the back stack</h3>
+
+<p>If the user leaves a task for a long time, the system clears the task of all activities except
+the root activity. When the user returns to the task again, only the root activity is restored.
+The system behaves this way, because, after an extended amount of time, users likely have abandoned
+what they were doing before and are returning to the task to begin something new. </p>
+
+<p>There are some activity attributes that you can use to modify this behavior: </p>
+
+<dl>
+<dt><code><a
+href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetainTaskState</a></code>
+</dt>
+<dd>If this attribute is set to {@code "true"} in the root activity of a task,
+the default behavior just described does not happen.
+The task retains all activities in its stack even after a long period.</dd>
+
+<dt><code><a
+href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch</a></code></dt>
+<dd>If this attribute is set to {@code "true"} in the root activity of a task,
+the stack is cleared down to the root activity whenever the user leaves the task
+and returns to it. In other words, it's the opposite of <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#always">{@code
+alwaysRetainTaskState}</a>. The user always returns to the task in its
+initial state, even after a leaving the task for only a moment.</dd>
+
+<dt><code><a
+href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTaskLaunch</a></code>
+</dt>
+<dd>This attribute is like <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#clear">{@code clearTaskOnLaunch}</a>,
+but it operates on a
+single activity, not an entire task. It can also cause any activity to go
+away, including the root activity. When it's set to {@code "true"}, the
+activity remains part of the task only for the current session. If the user
+leaves and then returns to the task, it is no longer present.</dd>
+</dl>
+
+
+
+
+<h3 id="Starting">Starting a task</h3>
+
+<p>You can set up an activity as the entry point for a task by giving it an intent filter with
+{@code "android.intent.action.MAIN"} as the specified action and {@code
+"android.intent.category.LAUNCHER"} as the specified category. For example:</p>
+
+<pre>
+<activity ... >
+ <intent-filter ... >
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ ...
+</activity>
+</pre>
+
+<p>An intent filter of this kind causes an icon and label for the
+activity to be displayed in the application launcher, giving users a way to launch the activity and
+to return to the task that it creates any time after it has been launched.
+</p>
+
+<p>This second ability is important: Users must be able to leave a task and then come back to it
+later using this activity launcher. For this reason, the two <a href="#LaunchModes">launch
+modes</a> that mark activities as always initiating a task, {@code "singleTask"} and "{@code
+"singleInstance"}, should be used only when the activity has an {@link
+android.content.Intent#ACTION_MAIN}
+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 key. The task is now sent to the background and not
+visible. Because it is not represented in the application launcher, the user has no way to return to
+the task.
+</p>
+
+<p>For those cases where you don't want the user to be able to return to an activity, set the
+ <code><a
+href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> element's
+<a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code
+finishOnTaskLaunch}</a> to {@code "true"} (see <a
+href="#Clearing">Clearing the stack</a>).</p>
+
+
+
+
+<h2>Beginner's Path</h2>
+
+<p>For more information about how to use intents to
+activate other application components and publish the intents to which your components
+respond, continue with the <b><a
+href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent
+Filters</a></b> document.</p>
diff --git a/docs/html/guide/topics/intents/intents-filters.jd b/docs/html/guide/topics/intents/intents-filters.jd
index bd1d694..5905214 100644
--- a/docs/html/guide/topics/intents/intents-filters.jd
+++ b/docs/html/guide/topics/intents/intents-filters.jd
@@ -3,15 +3,6 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Key classes</h2>
-<ol>
-<li>{@link android.content.Intent}</li>
-<li>{@link android.content.IntentFilter}</li>
-<li>{@link android.app.Activity}</li>
-<li>{@link android.app.Service}</li>
-<li>{@link android.content.BroadcastReceiver}</li>
-<li>{@link android.content.pm.PackageManager}</li>
-</ol>
<h2>In this document</h2>
<ol>
@@ -22,6 +13,15 @@
<li style="margin-left: 2em"><a href="#imatch">Using intent matching</a></li>
<li><a href="#npex">Note Pad Example</a></li>
</ol>
+
+<h2>Key classes</h2>
+<ol>
+<li>{@link android.content.Intent}</li>
+<li>{@link android.content.IntentFilter}</li>
+<li>{@link android.content.BroadcastReceiver}</li>
+<li>{@link android.content.pm.PackageManager}</li>
+</ol>
+
</div>
</div>
diff --git a/docs/html/guide/topics/media/index.jd b/docs/html/guide/topics/media/index.jd
index 96c500c..558d453 100644
--- a/docs/html/guide/topics/media/index.jd
+++ b/docs/html/guide/topics/media/index.jd
@@ -4,7 +4,7 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Audio/Video quickview</h2>
+<h2>Quickview</h2>
<ul>
<li>Audio playback and record</li>
<li>Video playback</li>
@@ -12,14 +12,6 @@
<li>Built-in codecs for a variety of media. See <a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media Formats</a></li>
</ul>
-<h2>Key classes</h2>
-<ol>
-<li>{@link android.media.MediaPlayer MediaPlayer} (all available formats)</li>
-<li>{@link android.media.MediaRecorder MediaRecorder} (all available formats)</li>
-<li>{@link android.media.JetPlayer JetPlayer} (playback, JET content)</li>
-<li>{@link android.media.SoundPool SoundPool} (sound management)</li>
-</ol>
-
<h2>In this document</h2>
<ol>
<li><a href="#playback.html">Audio and Video Playback</a>
@@ -32,6 +24,14 @@
<li><a href="#capture">Audio Capture</a></li>
</ol>
+<h2>Key classes</h2>
+<ol>
+<li>{@link android.media.MediaPlayer MediaPlayer}</li>
+<li>{@link android.media.MediaRecorder MediaRecorder}</li>
+<li>{@link android.media.JetPlayer JetPlayer}</li>
+<li>{@link android.media.SoundPool SoundPool}</li>
+</ol>
+
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a></li>
diff --git a/docs/html/guide/topics/providers/content-providers.jd b/docs/html/guide/topics/providers/content-providers.jd
index da4e7a1..2aed5e1 100644
--- a/docs/html/guide/topics/providers/content-providers.jd
+++ b/docs/html/guide/topics/providers/content-providers.jd
@@ -3,12 +3,6 @@
<div id="qv-wrapper">
<div id="qv">
-<h2>Key classes</h2>
-<ol>
-<li>{@link android.content.ContentProvider}</li>
-<li>{@link android.content.ContentResolver}</li>
-<li>{@link android.database.Cursor}</li>
-</ol>
<h2>In this document</h2>
<ol>
@@ -18,6 +12,13 @@
<li><a href="#creating">Creating a content provider</a></li>
<li><a href="#urisum">Content URI summary</a></li>
</ol>
+
+<h2>Key classes</h2>
+<ol>
+<li>{@link android.content.ContentProvider}</li>
+<li>{@link android.content.ContentResolver}</li>
+<li>{@link android.database.Cursor}</li>
+</ol>
</div>
</div>
diff --git a/docs/html/guide/topics/search/adding-custom-suggestions.jd b/docs/html/guide/topics/search/adding-custom-suggestions.jd
index ce0c619..c8f06b9 100644
--- a/docs/html/guide/topics/search/adding-custom-suggestions.jd
+++ b/docs/html/guide/topics/search/adding-custom-suggestions.jd
@@ -33,7 +33,7 @@
<li>{@link android.content.ContentProvider}</li>
</ol>
-<h2>Related Samples</h2>
+<h2>Related samples</h2>
<ol>
<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
Dictionary</a></li>
diff --git a/docs/html/guide/topics/search/index.jd b/docs/html/guide/topics/search/index.jd
index 78e0be2..f563715 100644
--- a/docs/html/guide/topics/search/index.jd
+++ b/docs/html/guide/topics/search/index.jd
@@ -13,7 +13,7 @@
<ol>
<li><a href="searchable-config.html">Searchable Configuration</a></li>
</ol>
-<h2>Related Samples</h2>
+<h2>Related samples</h2>
<ol>
<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
Dictionary</a></li>
diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd
index 49c6627..49938b4 100644
--- a/docs/html/guide/topics/search/search-dialog.jd
+++ b/docs/html/guide/topics/search/search-dialog.jd
@@ -29,7 +29,7 @@
<li>{@link android.app.SearchManager}</li>
</ol>
-<h2>Related Samples</h2>
+<h2>Related samples</h2>
<ol>
<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
Dictionary</a></li>
diff --git a/docs/html/guide/topics/testing/testing_android.jd b/docs/html/guide/topics/testing/testing_android.jd
index 513e472..1d5f911 100755
--- a/docs/html/guide/topics/testing/testing_android.jd
+++ b/docs/html/guide/topics/testing/testing_android.jd
@@ -50,14 +50,14 @@
<a href="#NextSteps">Next Steps</a>
</li>
</ol>
- <h2>Key Classes and Packages</h2>
+ <h2>Key classes</h2>
<ol>
<li>{@link android.test.InstrumentationTestRunner}</li>
<li>{@link android.test}</li>
<li>{@link android.test.mock}</li>
<li>{@link junit.framework}</li>
</ol>
- <h2>Related Tutorials</h2>
+ <h2>Related tutorials</h2>
<ol>
<li>
<a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">
@@ -67,7 +67,7 @@
<a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
</li>
</ol>
- <h2>See Also</h2>
+ <h2>See also</h2>
<ol>
<li>
<a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
diff --git a/docs/html/guide/topics/ui/binding.jd b/docs/html/guide/topics/ui/binding.jd
index 6ac0bb0..26364ee 100644
--- a/docs/html/guide/topics/ui/binding.jd
+++ b/docs/html/guide/topics/ui/binding.jd
@@ -11,11 +11,11 @@
<li><a href="#HandlingUserSelections">Handling User Selections</a></li>
</ol>
- <h2>See also</h2>
+ <h2>Related tutorials</h2>
<ol>
- <li><a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Hello Spinner tutorial</a></li>
- <li><a href="{@docRoot}resources/tutorials/views/hello-listview.html">Hello ListView tutorial</a></li>
- <li><a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Hello GridView tutorial</a></li>
+ <li><a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Spinner</a></li>
+ <li><a href="{@docRoot}resources/tutorials/views/hello-listview.html">List View</a></li>
+ <li><a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Grid View</a></li>
</ol>
</div>
</div>
diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index 5c12db9..fe641a2 100644
--- a/docs/html/guide/topics/ui/declaring-layout.jd
+++ b/docs/html/guide/topics/ui/declaring-layout.jd
@@ -5,12 +5,6 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>Key classes</h2>
- <ol>
- <li>{@link android.view.View}</li>
- <li>{@link android.view.ViewGroup}</li>
- <li>{@link android.view.ViewGroup.LayoutParams}</li>
- </ol>
<h2>In this document</h2>
<ol>
<li><a href="#write">Write the XML</a></li>
@@ -26,6 +20,12 @@
<li><a href="#example">Example Layout</a></li>
</ol>
+ <h2>Key classes</h2>
+ <ol>
+ <li>{@link android.view.View}</li>
+ <li>{@link android.view.ViewGroup}</li>
+ <li>{@link android.view.ViewGroup.LayoutParams}</li>
+ </ol>
</div>
</div>
diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd
index f47a709..879eb8b 100644
--- a/docs/html/guide/topics/ui/dialogs.jd
+++ b/docs/html/guide/topics/ui/dialogs.jd
@@ -5,10 +5,6 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>Key classes</h2>
- <ol>
- <li>{@link android.app.Dialog}</li>
- </ol>
<h2>In this document</h2>
<ol>
<li><a href="#ShowingADialog">Showing a Dialog</a></li>
@@ -26,6 +22,11 @@
</li>
<li><a href="#CustomDialog">Creating a Custom Dialog</a></li>
</ol>
+
+ <h2>Key classes</h2>
+ <ol>
+ <li>{@link android.app.Dialog}</li>
+ </ol>
</div>
</div>
diff --git a/docs/html/guide/topics/ui/index.jd b/docs/html/guide/topics/ui/index.jd
index abcf6be..375c9fe 100644
--- a/docs/html/guide/topics/ui/index.jd
+++ b/docs/html/guide/topics/ui/index.jd
@@ -4,13 +4,6 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>Key classes</h2>
- <ol>
- <li>{@link android.view.View}</li>
- <li>{@link android.view.ViewGroup}</li>
- <li>{@link android.widget Widget classes}</li>
- </ol>
-
<h2>In this document</h2>
<ol>
<li><a href="#ViewHierarchy">View Hierarchy</a></li>
@@ -25,6 +18,13 @@
</ol>
</li>
</ol>
+
+ <h2>Key classes</h2>
+ <ol>
+ <li>{@link android.view.View}</li>
+ <li>{@link android.view.ViewGroup}</li>
+ <li>{@link android.widget Widget classes}</li>
+ </ol>
</div>
</div>
diff --git a/docs/html/guide/topics/ui/notifiers/index.jd b/docs/html/guide/topics/ui/notifiers/index.jd
index f7ccce7..d29324c 100644
--- a/docs/html/guide/topics/ui/notifiers/index.jd
+++ b/docs/html/guide/topics/ui/notifiers/index.jd
@@ -3,13 +3,7 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>In this document</h2>
- <ol>
- <li><a href="#Toast">Toast Notification</a></li>
- <li><a href="#StatusBarNotification">Status Bar Notification</a></li>
- <li><a href="#Dialog">Dialog Notification</a></li>
- </ol>
- <h2>More about</h2>
+ <h2>Topics</h2>
<ol>
<li><a href="toasts.html">Creating Toast Notifications</a></li>
<li><a href="notifications.html">Creating Status Bar Notifications</a></li>
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index a0dd9f1..abc945a 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -5,18 +5,21 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>Key classes</h2>
- <ol>
- <li>{@link android.app.Notification}</li>
- <li>{@link android.app.NotificationManager}</li>
- </ol>
+ <h2>Quickview</h2>
+ <ul>
+ <li>A status bar notification allows your application to notify the user of an event
+without interupting their current activity</li>
+ <li>You can attach an intent to your notification that the system will initiate when the
+user clicks it</li>
+ </ul>
+
<h2>In this document</h2>
<ol>
<li><a href="#Basics">The Basics</a></li>
<li><a href="#ManageYourNotifications">Managing your Notifications</a></li>
<li><a href="#CreateANotification">Creating a Notification</a>
<ol>
- <li><a href="#Update">Updating the notification</a></li>
+ <li><a href="#Updating">Updating the notification</a></li>
<li><a href="#Sound">Adding a sound</a></li>
<li><a href="#Vibration">Adding vibration</a></li>
<li><a href="#Lights">Adding flashing lights</a></li>
@@ -25,6 +28,11 @@
</li>
<li><a href="#CustomExpandedView">Creating a Custom Expanded View</a></li>
</ol>
+ <h2>Key classes</h2>
+ <ol>
+ <li>{@link android.app.Notification}</li>
+ <li>{@link android.app.NotificationManager}</li>
+ </ol>
</div>
</div>
diff --git a/docs/html/guide/topics/ui/notifiers/toasts.jd b/docs/html/guide/topics/ui/notifiers/toasts.jd
index 5b324d2..0d3e10c 100644
--- a/docs/html/guide/topics/ui/notifiers/toasts.jd
+++ b/docs/html/guide/topics/ui/notifiers/toasts.jd
@@ -5,16 +5,24 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>Key classes</h2>
+ <h2>Quickview</h2>
<ol>
- <li>{@link android.widget.Toast}</li>
+ <li>A toast is a message that appears on the surface of the screen for a moment, but it
+does not take focus (or pause the current activity), so it cannot accept user input</li>
+ <li>You can customize the toast layout to include images</li>
</ol>
+
<h2>In this document</h2>
<ol>
<li><a href="#Basics">The Basics</a></li>
- <li><a href="#Position">Positioning your Toast</a></li>
+ <li><a href="#Positioning">Positioning your Toast</a></li>
<li><a href="#CustomToastView">Creating a Custom Toast View</a></li>
</ol>
+
+ <h2>Key classes</h2>
+ <ol>
+ <li>{@link android.widget.Toast}</li>
+ </ol>
</div>
</div>
diff --git a/docs/html/guide/topics/ui/ui-events.jd b/docs/html/guide/topics/ui/ui-events.jd
index ccef64f..7d7bfaf 100644
--- a/docs/html/guide/topics/ui/ui-events.jd
+++ b/docs/html/guide/topics/ui/ui-events.jd
@@ -13,9 +13,9 @@
<li><a href="#HandlingFocus">Handling Focus</a></li>
</ol>
- <h2>See also</h2>
+ <h2>Related tutorials</h2>
<ol>
- <li><a href="{@docRoot}resources/tutorials/views/hello-formstuff.html">Hello Form Stuff tutorial</a></li>
+ <li><a href="{@docRoot}resources/tutorials/views/hello-formstuff.html">Form Stuff</a></li>
</ol>
</div>
</div>
diff --git a/docs/html/guide/topics/wireless/bluetooth.jd b/docs/html/guide/topics/wireless/bluetooth.jd
index a8ff007..fa2875b 100644
--- a/docs/html/guide/topics/wireless/bluetooth.jd
+++ b/docs/html/guide/topics/wireless/bluetooth.jd
@@ -3,14 +3,13 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>Key Classes</h2>
- <ol>
- <li>{@link android.bluetooth.BluetoothAdapter}</li>
- <li>{@link android.bluetooth.BluetoothDevice}</li>
- <li>{@link android.bluetooth.BluetoothSocket}</li>
- <li>{@link android.bluetooth.BluetoothServerSocket}</li>
- </ol>
+ <h2>Quickview</h2>
+ <ul>
+ <li>Android's bluetooth APIs allow your application to perform wireless data transactions with
+other devices</li>
+ </ul>
+
<h2>In this document</h2>
<ol>
<li><a href="#TheBasics">The Basics</a></li>
@@ -33,11 +32,18 @@
</li>
<li><a href="#ManagingAConnection">Managing a Connection</a></li>
</ol>
-
- <h2>See also</h2>
+
+ <h2>Key classes</h2>
<ol>
- <li><a href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat sample
- app</a></li>
+ <li>{@link android.bluetooth.BluetoothAdapter}</li>
+ <li>{@link android.bluetooth.BluetoothDevice}</li>
+ <li>{@link android.bluetooth.BluetoothSocket}</li>
+ <li>{@link android.bluetooth.BluetoothServerSocket}</li>
+ </ol>
+
+ <h2>Related samples</h2>
+ <ol>
+ <li><a href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat</a></li>
</ol>
</div>
diff --git a/docs/html/images/fundamentals/diagram_backstack.png b/docs/html/images/fundamentals/diagram_backstack.png
new file mode 100644
index 0000000..2c6e33f
--- /dev/null
+++ b/docs/html/images/fundamentals/diagram_backstack.png
Binary files differ
diff --git a/docs/html/images/fundamentals/diagram_backstack_singletask_multiactivity.png b/docs/html/images/fundamentals/diagram_backstack_singletask_multiactivity.png
new file mode 100644
index 0000000..d6a21d7
--- /dev/null
+++ b/docs/html/images/fundamentals/diagram_backstack_singletask_multiactivity.png
Binary files differ
diff --git a/docs/html/images/fundamentals/diagram_multiple_instances.png b/docs/html/images/fundamentals/diagram_multiple_instances.png
new file mode 100644
index 0000000..380e7788
--- /dev/null
+++ b/docs/html/images/fundamentals/diagram_multiple_instances.png
Binary files differ
diff --git a/docs/html/images/fundamentals/diagram_multitasking.png b/docs/html/images/fundamentals/diagram_multitasking.png
new file mode 100644
index 0000000..b8c7b45
--- /dev/null
+++ b/docs/html/images/fundamentals/diagram_multitasking.png
Binary files differ
diff --git a/docs/html/images/fundamentals/restore_instance.png b/docs/html/images/fundamentals/restore_instance.png
new file mode 100644
index 0000000..fa428a7
--- /dev/null
+++ b/docs/html/images/fundamentals/restore_instance.png
Binary files differ
diff --git a/docs/html/images/home/market-intl.png b/docs/html/images/home/market-intl.png
new file mode 100644
index 0000000..2bb22f1
--- /dev/null
+++ b/docs/html/images/home/market-intl.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index f37a122..049df62 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -11,12 +11,14 @@
</div><!-- end homeTitle -->
<div id="announcement-block">
<!-- total max width is 520px -->
- <img src="{@docRoot}images/home/io-logo.png" alt="Google IO
-2010" width="200" height="41" style="padding:22px 12px;"/>
+ <img src="{@docRoot}images/home/market-intl.png" alt="Android
+Market" width="104" height="120" style="padding:10px 60px 5px" />
<div id="announcement" style="width:295px">
-<p>Thanks to everyone who visited us at Google I/O in San Francisco! Stay tuned for
-videos and slides from the Android sessions, which will be posted at the Google I/O web site.</p><p><a
-href="http://code.google.com/events/io/2010/sessions.html#Android">Learn more »</a></p>
+<p>We're pleased to announce that paid apps are available in more locations of the world! Developers
+from 20 more locations can now sell paid apps on Android Market. Users in more locations will also
+soon be able to purchase apps.</p><p><a
+href="http://android-developers.blogspot.com/2010/09/more-countries-more-sellers-more-buyers.html">
+Learn more »</a></p>
</div> <!-- end annoucement -->
</div> <!-- end annoucement-block -->
</div><!-- end topAnnouncement -->
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 985d700..2c076b3 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -182,6 +182,24 @@
mRS.nAllocationRead(mID, d);
}
+ public void resize(int dimX) {
+ if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) {
+ throw new IllegalStateException("Resize only support for 1D allocations at this time.");
+ }
+ mRS.nAllocationResize1D(mID, dimX);
+ }
+
+ /*
+ public void resize(int dimX, int dimY) {
+ if ((mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) {
+ throw new IllegalStateException("Resize only support for 2D allocations at this time.");
+ }
+ if (mType.getY() == 0) {
+ throw new IllegalStateException("Resize only support for 2D allocations at this time.");
+ }
+ mRS.nAllocationResize2D(mID, dimX, dimY);
+ }
+ */
public class Adapter1D extends BaseObj {
Adapter1D(int id, RenderScript rs) {
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 3c0b4e5..0088373 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -254,6 +254,15 @@
return rsnAllocationGetType(mContext, id);
}
+ native void rsnAllocationResize1D(int con, int id, int dimX);
+ synchronized void nAllocationResize1D(int id, int dimX) {
+ rsnAllocationResize1D(mContext, id, dimX);
+ }
+ native void rsnAllocationResize2D(int con, int id, int dimX, int dimY);
+ synchronized void nAllocationResize2D(int id, int dimX, int dimY) {
+ rsnAllocationResize2D(mContext, id, dimX, dimY);
+ }
+
native int rsnFileA3DCreateFromAssetStream(int con, int assetStream);
synchronized int nFileA3DCreateFromAssetStream(int assetStream) {
return rsnFileA3DCreateFromAssetStream(mContext, assetStream);
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 67a2b63..8f1e93c 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -587,6 +587,20 @@
return (jint) rsAllocationGetType(con, (RsAllocation)a);
}
+static void
+nAllocationResize1D(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint dimX)
+{
+ LOG_API("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i)", con, (RsAllocation)alloc, dimX);
+ rsAllocationResize1D(con, (RsAllocation)alloc, dimX);
+}
+
+static void
+nAllocationResize2D(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint dimX, jint dimY)
+{
+ LOG_API("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i), sizeY(%i)", con, (RsAllocation)alloc, dimX, dimY);
+ rsAllocationResize2D(con, (RsAllocation)alloc, dimX, dimY);
+}
+
// -----------------------------------
static int
@@ -1252,6 +1266,8 @@
{"rsnAllocationRead", "(II[I)V", (void*)nAllocationRead_i },
{"rsnAllocationRead", "(II[F)V", (void*)nAllocationRead_f },
{"rsnAllocationGetType", "(II)I", (void*)nAllocationGetType},
+{"rsnAllocationResize1D", "(III)V", (void*)nAllocationResize1D },
+{"rsnAllocationResize2D", "(IIII)V", (void*)nAllocationResize2D },
{"rsnAdapter1DBindAllocation", "(III)V", (void*)nAdapter1DBindAllocation },
{"rsnAdapter1DSetConstraint", "(IIII)V", (void*)nAdapter1DSetConstraint },
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index adf6ee2..701df83 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -18,6 +18,8 @@
#include <GLES2/gl2.h>
+#include <SkCanvas.h>
+
#include <utils/threads.h>
#include "TextureCache.h"
@@ -192,8 +194,12 @@
// decoding happened
texture->blend = !bitmap->isOpaque();
break;
+ case SkBitmap::kIndex8_Config:
+ uploadPalettedTexture(resize, bitmap, texture->width, texture->height);
+ texture->blend = false;
+ break;
default:
- LOGW("Unsupported bitmap config");
+ LOGW("Unsupported bitmap config: %d", bitmap->getConfig());
break;
}
@@ -204,6 +210,20 @@
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
+void TextureCache::uploadPalettedTexture(bool resize, SkBitmap* bitmap,
+ uint32_t width, uint32_t height) {
+ SkBitmap rgbaBitmap;
+ rgbaBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ rgbaBitmap.allocPixels();
+ rgbaBitmap.eraseColor(0);
+
+ SkCanvas canvas(rgbaBitmap);
+ canvas.drawBitmap(*bitmap, 0.0f, 0.0f, NULL);
+
+ uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), height,
+ GL_UNSIGNED_BYTE, rgbaBitmap.getPixels());
+}
+
void TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei width, GLsizei height,
GLenum type, const GLvoid * data) {
if (resize) {
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 7cf66d9..34c5455 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -79,6 +79,7 @@
*/
void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false);
+ void uploadPalettedTexture(bool resize, SkBitmap* bitmap, uint32_t width, uint32_t height);
void uploadToTexture(bool resize, GLenum format, GLsizei width, GLsizei height,
GLenum type, const GLvoid * data);
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 37c418b..05c1a48 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -83,7 +83,6 @@
rsElement.cpp \
rsFileA3D.cpp \
rsFont.cpp \
- rsLight.cpp \
rsLocklessFifo.cpp \
rsObjectBase.cpp \
rsMatrix.cpp \
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 13ae1fb..66e27f3 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -40,7 +40,6 @@
typedef void * RsScript;
typedef void * RsMesh;
typedef void * RsType;
-typedef void * RsLight;
typedef void * RsObjectBase;
typedef void * RsProgram;
@@ -242,7 +241,6 @@
RS_A3D_CLASS_ID_PROGRAM_STORE,
RS_A3D_CLASS_ID_SAMPLER,
RS_A3D_CLASS_ID_ANIMATION,
- RS_A3D_CLASS_ID_LIGHT,
RS_A3D_CLASS_ID_ADAPTER_1D,
RS_A3D_CLASS_ID_ADAPTER_2D,
RS_A3D_CLASS_ID_SCRIPT_C
diff --git a/libs/rs/RenderScriptEnv.h b/libs/rs/RenderScriptEnv.h
index c83ece4..b82eaf1 100644
--- a/libs/rs/RenderScriptEnv.h
+++ b/libs/rs/RenderScriptEnv.h
@@ -13,8 +13,6 @@
typedef void * RsType;
typedef void * RsProgramFragment;
typedef void * RsProgramStore;
-typedef void * RsLight;
-
typedef struct {
float m[16];
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
index a15c4a1..0990da3 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
@@ -84,8 +84,6 @@
private Allocation mTexTransparent;
private Allocation mTexChecker;
- private Allocation mAllocPV;
-
private Mesh mMbyNMesh;
private Mesh mTorus;
@@ -95,7 +93,6 @@
Font mFontSerifItalic;
Font mFontSerifBoldItalic;
Font mFontMono;
-
private Allocation mTextAlloc;
private ScriptC_rsrenderstates mScript;
@@ -267,12 +264,15 @@
mFontSerifBoldItalic = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8);
mFontMono = Font.createFromFamily(mRS, mRes, "mono", Font.Style.NORMAL, 8);
+ mTextAlloc = Allocation.createFromString(mRS, "String from allocation");
+
mScript.set_gFontSans(mFontSans);
mScript.set_gFontSerif(mFontSerif);
mScript.set_gFontSerifBold(mFontSerifBold);
mScript.set_gFontSerifItalic(mFontSerifItalic);
mScript.set_gFontSerifBoldItalic(mFontSerifBoldItalic);
mScript.set_gFontMono(mFontMono);
+ mScript.set_gTextAlloc(mTextAlloc);
}
private void initMesh() {
diff --git a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
index b471504..77384ef 100644
--- a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
+++ b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
@@ -42,6 +42,7 @@
rs_font gFontSerifItalic;
rs_font gFontSerifBoldItalic;
rs_font gFontMono;
+rs_allocation gTextAlloc;
int gDisplayMode;
@@ -70,7 +71,7 @@
#pragma rs export_var(gProgStoreBlendNoneDepth, gProgStoreBlendNone, gProgStoreBlendAlpha, gProgStoreBlendAdd)
#pragma rs export_var(gTexOpaque, gTexTorus, gTexTransparent, gTexChecker)
#pragma rs export_var(gMbyNMesh, gTorusMesh)
-#pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono)
+#pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono, gTextAlloc)
#pragma rs export_var(gLinearClamp, gLinearWrap, gMipLinearWrap, gMipLinearAniso8, gMipLinearAniso15, gNearestClamp)
#pragma rs export_var(gCullBack, gCullFront, gCullNone)
#pragma rs export_var(gVSConstants, gFSConstants, gVSInputs, gProgVertexCustom, gProgFragmentCustom, gProgFragmentMultitex)
@@ -85,7 +86,7 @@
void displayFontSamples() {
rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
- int yPos = 30;
+ int yPos = 100;
rsgBindFont(gFontSans);
rsgDrawText("Sans font sample", 30, yPos);
yPos += 30;
@@ -107,6 +108,47 @@
yPos += 30;
rsgBindFont(gFontMono);
rsgDrawText("Monospace font sample", 30, yPos);
+ yPos += 50;
+
+ // Now use text metrics to center the text
+ uint width = rsgGetWidth();
+ uint height = rsgGetHeight();
+ int left = 0, right = 0, top = 0, bottom = 0;
+
+ rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
+ rsgBindFont(gFontSerifBoldItalic);
+
+ rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom);
+ int centeredPos = width / 2 - (right - left) / 2;
+ rsgDrawText(gTextAlloc, centeredPos, yPos);
+ yPos += 30;
+
+ const char* text = "Centered Text Sample";
+ rsgMeasureText(text, &left, &right, &top, &bottom);
+ centeredPos = width / 2 - (right - left) / 2;
+ rsgDrawText(text, centeredPos, yPos);
+ yPos += 30;
+
+ rsgBindFont(gFontSans);
+ text = "More Centered Text Samples";
+ rsgMeasureText(text, &left, &right, &top, &bottom);
+ centeredPos = width / 2 - (right - left) / 2;
+ rsgDrawText(text, centeredPos, yPos);
+ yPos += 30;
+
+ // Now draw bottom and top right aligned text
+ text = "Top-right aligned text";
+ rsgMeasureText(text, &left, &right, &top, &bottom);
+ rsgDrawText(text, width - right, top);
+
+ text = "Top-left";
+ rsgMeasureText(text, &left, &right, &top, &bottom);
+ rsgDrawText(text, -left, top);
+
+ text = "Bottom-right aligned text";
+ rsgMeasureText(text, &left, &right, &top, &bottom);
+ rsgDrawText(text, width - right, height + bottom);
+
}
void bindProgramVertexOrtho() {
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index a4752f4..0da637e 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -280,6 +280,17 @@
ret const void*
}
+AllocationResize1D {
+ param RsAllocation va
+ param uint32_t dimX
+ }
+
+AllocationResize2D {
+ param RsAllocation va
+ param uint32_t dimX
+ param uint32_t dimY
+ }
+
SamplerBegin {
}
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 0356e4d..2e9e0b3 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -488,12 +488,13 @@
}
}
-void Allocation::incRefs(const void *ptr, size_t ct) const
+void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const
{
const uint8_t *p = static_cast<const uint8_t *>(ptr);
const Element *e = mType->getElement();
uint32_t stride = e->getSizeBytes();
+ p += stride * startOff;
while (ct > 0) {
e->incRefs(p);
ct --;
@@ -501,12 +502,13 @@
}
}
-void Allocation::decRefs(const void *ptr, size_t ct) const
+void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const
{
const uint8_t *p = static_cast<const uint8_t *>(ptr);
const Element *e = mType->getElement();
uint32_t stride = e->getSizeBytes();
+ p += stride * startOff;
while (ct > 0) {
e->decRefs(p);
ct --;
@@ -514,6 +516,37 @@
}
}
+void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len)
+{
+}
+
+void Allocation::resize1D(Context *rsc, uint32_t dimX)
+{
+ Type *t = mType->cloneAndResize1D(rsc, dimX);
+
+ uint32_t oldDimX = mType->getDimX();
+ if (dimX == oldDimX) {
+ return;
+ }
+
+ if (dimX < oldDimX) {
+ decRefs(mPtr, oldDimX - dimX, dimX);
+ }
+ mPtr = realloc(mPtr, t->getSizeBytes());
+
+ if (dimX > oldDimX) {
+ const Element *e = mType->getElement();
+ uint32_t stride = e->getSizeBytes();
+ memset(((uint8_t *)mPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX));
+ }
+ mType.set(t);
+}
+
+void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY)
+{
+ LOGE("not implemented");
+}
+
/////////////////
//
@@ -822,6 +855,18 @@
a->read(data);
}
+void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX)
+{
+ Allocation *a = static_cast<Allocation *>(va);
+ a->resize1D(rsc, dimX);
+}
+
+void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY)
+{
+ Allocation *a = static_cast<Allocation *>(va);
+ a->resize2D(rsc, dimX, dimY);
+}
+
const void* rsi_AllocationGetType(Context *rsc, RsAllocation va)
{
Allocation *a = static_cast<Allocation *>(va);
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index ce5372f..24e245f 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -55,6 +55,10 @@
void uploadToBufferObject(const Context *rsc);
uint32_t getBufferObjectID() const {return mBufferID;}
+ void copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len);
+
+ void resize1D(Context *rsc, uint32_t dimX);
+ void resize2D(Context *rsc, uint32_t dimX, uint32_t dimY);
void data(Context *rsc, const void *data, uint32_t sizeBytes);
void subData(Context *rsc, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes);
@@ -86,8 +90,8 @@
bool getIsTexture() const {return mIsTexture;}
bool getIsBufferObject() const {return mIsVertexBuffer;}
- void incRefs(const void *ptr, size_t ct) const;
- void decRefs(const void *ptr, size_t ct) const;
+ void incRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
+ void decRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
void sendDirty() const;
bool getHasGraphicsMipmaps() const {return mTextureGenMipmap;}
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 6940033..30add62 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -188,6 +188,9 @@
mTimeFrame = mTimeLast;
mTimeLastFrame = mTimeLast;
mTimerActive = RS_TIMER_INTERNAL;
+ mAverageFPSFrameCount = 0;
+ mAverageFPSStartTime = mTimeLast;
+ mAverageFPS = 0;
timerReset();
}
@@ -195,6 +198,16 @@
{
mTimeLastFrame = mTimeFrame;
mTimeFrame = getTime();
+ // Update average fps
+ const uint64_t averageFramerateInterval = 1000 * 1000000;
+ mAverageFPSFrameCount ++;
+ uint64_t inverval = mTimeFrame - mAverageFPSStartTime;
+ if(inverval >= averageFramerateInterval) {
+ inverval = inverval / 1000000;
+ mAverageFPS = (mAverageFPSFrameCount * 1000) / inverval;
+ mAverageFPSFrameCount = 0;
+ mAverageFPSStartTime = mTimeFrame;
+ }
}
void Context::timerSet(Timers tm)
@@ -218,12 +231,13 @@
if (props.mLogTimes) {
- LOGV("RS: Frame (%i), Script %2.1f (%i), Clear & Swap %2.1f (%i), Idle %2.1f (%lli), Internal %2.1f (%lli)",
+ LOGV("RS: Frame (%i), Script %2.1f (%i), Clear & Swap %2.1f (%i), Idle %2.1f (%lli), Internal %2.1f (%lli), Avg fps: %u",
mTimeMSLastFrame,
100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript,
100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap,
100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
- 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000);
+ 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000,
+ mAverageFPS);
}
}
@@ -255,17 +269,17 @@
void Context::displayDebugStats()
{
char buffer[128];
- sprintf(buffer, "Frame %i ms, Script %i ms", mTimeMSLastFrame, mTimeMSLastScript);
+ sprintf(buffer, "Avg fps %u, Frame %i ms, Script %i ms", mAverageFPS, mTimeMSLastFrame, mTimeMSLastScript);
float oldR, oldG, oldB, oldA;
mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA);
+ uint32_t bufferLen = strlen(buffer);
- float shadowCol = 0.2f;
+ float shadowCol = 0.1f;
mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f);
- mStateFont.renderText(buffer, 5, getHeight() - 5);
+ mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 6);
- float textCol = 0.9f;
- mStateFont.setFontColor(textCol, textCol, textCol, 1.0f);
- mStateFont.renderText(buffer, 4, getHeight() - 6);
+ mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f);
+ mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 7);
mStateFont.setFontColor(oldR, oldG, oldB, oldA);
}
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index dabe196..8a8b8a8 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -30,7 +30,6 @@
#include "rsAllocation.h"
#include "rsAdapter.h"
#include "rsSampler.h"
-#include "rsLight.h"
#include "rsFont.h"
#include "rsProgramFragment.h"
#include "rsProgramStore.h"
@@ -94,7 +93,6 @@
ProgramStoreState mStateFragmentStore;
ProgramRasterState mStateRaster;
ProgramVertexState mStateVertex;
- LightState mStateLight;
VertexArrayState mStateVertexArray;
FontState mStateFont;
@@ -296,6 +294,9 @@
uint32_t mTimeMSLastFrame;
uint32_t mTimeMSLastScript;
uint32_t mTimeMSLastSwap;
+ uint32_t mAverageFPSFrameCount;
+ uint64_t mAverageFPSStartTime;
+ uint32_t mAverageFPS;
};
}
diff --git a/libs/rs/rsContextHostStub.h b/libs/rs/rsContextHostStub.h
index 06298e8..aa0205d 100644
--- a/libs/rs/rsContextHostStub.h
+++ b/libs/rs/rsContextHostStub.h
@@ -30,7 +30,6 @@
#include "rsAllocation.h"
#include "rsAdapter.h"
#include "rsSampler.h"
-#include "rsLight.h"
#include "rsProgramFragment.h"
#include "rsProgramStore.h"
#include "rsProgramRaster.h"
@@ -68,7 +67,6 @@
ProgramStoreState mStateFragmentStore;
//ProgramRasterState mStateRaster;
//ProgramVertexState mStateVertex;
- LightState mStateLight;
VertexArrayState mStateVertexArray;
//ScriptCState mScriptC;
diff --git a/libs/rs/rsFileA3D.cpp b/libs/rs/rsFileA3D.cpp
index 893598f..c90edc2 100644
--- a/libs/rs/rsFileA3D.cpp
+++ b/libs/rs/rsFileA3D.cpp
@@ -278,9 +278,6 @@
case RS_A3D_CLASS_ID_ANIMATION:
entry->mRsObj = Animation::createFromStream(mRSC, mReadStream);
break;
- case RS_A3D_CLASS_ID_LIGHT:
- entry->mRsObj = Light::createFromStream(mRSC, mReadStream);
- break;
case RS_A3D_CLASS_ID_ADAPTER_1D:
entry->mRsObj = Adapter1D::createFromStream(mRSC, mReadStream);
break;
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index c516ea9..b9de7e1 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -84,34 +84,95 @@
}
}
-void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y)
+void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y)
{
FontState *state = &mRSC->mStateFont;
- int nPenX = x + glyph->mBitmapLeft;
- int nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
+ int32_t nPenX = x + glyph->mBitmapLeft;
+ int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
- state->appendMeshQuad(nPenX, nPenY, 0,
- glyph->mBitmapMinU, glyph->mBitmapMaxV,
+ float u1 = glyph->mBitmapMinU;
+ float u2 = glyph->mBitmapMaxU;
+ float v1 = glyph->mBitmapMinV;
+ float v2 = glyph->mBitmapMaxV;
- nPenX + (int)glyph->mBitmapWidth, nPenY, 0,
- glyph->mBitmapMaxU, glyph->mBitmapMaxV,
+ int32_t width = (int32_t) glyph->mBitmapWidth;
+ int32_t height = (int32_t) glyph->mBitmapHeight;
- nPenX + (int)glyph->mBitmapWidth, nPenY - (int)glyph->mBitmapHeight, 0,
- glyph->mBitmapMaxU, glyph->mBitmapMinV,
-
- nPenX, nPenY - (int)glyph->mBitmapHeight, 0,
- glyph->mBitmapMinU, glyph->mBitmapMinV);
+ state->appendMeshQuad(nPenX, nPenY, 0, u1, v2,
+ nPenX + width, nPenY, 0, u2, v2,
+ nPenX + width, nPenY - height, 0, u2, v1,
+ nPenX, nPenY - height, 0, u1, v1);
}
-void Font::renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyphs, int x, int y)
+void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y,
+ uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) {
+ int32_t nPenX = x + glyph->mBitmapLeft;
+ int32_t nPenY = y + glyph->mBitmapTop;
+
+ uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth;
+ uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight;
+
+ FontState *state = &mRSC->mStateFont;
+ uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
+ const uint8_t* cacheBuffer = state->getTextTextureData();
+
+ uint32_t cacheX = 0, cacheY = 0;
+ int32_t bX = 0, bY = 0;
+ for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) {
+ for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) {
+ if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) {
+ LOGE("Skipping invalid index");
+ continue;
+ }
+ uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX];
+ bitmap[bY * bitmapW + bX] = tempCol;
+ }
+ }
+
+}
+
+void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) {
+ int32_t nPenX = x + glyph->mBitmapLeft;
+ int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
+
+ int32_t width = (int32_t) glyph->mBitmapWidth;
+ int32_t height = (int32_t) glyph->mBitmapHeight;
+
+ if (bounds->bottom > nPenY) {
+ bounds->bottom = nPenY;
+ }
+ if (bounds->left > nPenX) {
+ bounds->left = nPenX;
+ }
+ if (bounds->right < nPenX + width) {
+ bounds->right = nPenX + width;
+ }
+ if (bounds->top < nPenY + height) {
+ bounds->top = nPenY + height;
+ }
+}
+
+void Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y,
+ uint32_t start, int32_t numGlyphs,
+ RenderMode mode, Rect *bounds,
+ uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH)
{
if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) {
return;
}
- int penX = x, penY = y;
- int glyphsLeft = 1;
+ if(mode == Font::MEASURE) {
+ if (bounds == NULL) {
+ LOGE("No return rectangle provided to measure text");
+ return;
+ }
+ // Reset min and max of the bounding box to something large
+ bounds->set(1e6, -1e6, -1e6, 1e6);
+ }
+
+ int32_t penX = x, penY = y;
+ int32_t glyphsLeft = 1;
if(numGlyphs > 0) {
glyphsLeft = numGlyphs;
}
@@ -135,7 +196,17 @@
// If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
if(cachedGlyph->mIsValid) {
- drawCachedGlyph(cachedGlyph, penX, penY);
+ switch(mode) {
+ case FRAMEBUFFER:
+ drawCachedGlyph(cachedGlyph, penX, penY);
+ break;
+ case BITMAP:
+ drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH);
+ break;
+ case MEASURE:
+ measureCachedGlyph(cachedGlyph, penX, penY, bounds);
+ break;
+ }
}
penX += (cachedGlyph->mAdvance.x >> 6);
@@ -283,7 +354,7 @@
}
// Get the black gamma threshold
- int blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
+ int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) {
LOGD(" Setting text black gamma threshold to %s", property);
blackThreshold = atoi(property);
@@ -294,7 +365,7 @@
mBlackThreshold = (float)(blackThreshold) / 255.0f;
// Get the white gamma threshold
- int whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
+ int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) {
LOGD(" Setting text white gamma threshold to %s", property);
whiteThreshold = atoi(property);
@@ -397,13 +468,13 @@
uint32_t cacheWidth = getCacheTextureType()->getDimX();
- unsigned char *cacheBuffer = (unsigned char*)mTextTexture->getPtr();
- unsigned char *bitmapBuffer = bitmap->buffer;
+ uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr();
+ uint8_t *bitmapBuffer = bitmap->buffer;
uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) {
for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) {
- unsigned char tempCol = bitmapBuffer[bY * bitmap->width + bX];
+ uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX];
cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol;
}
}
@@ -487,7 +558,7 @@
mTextTexture->deferedUploadToTexture(mRSC, false, 0);
// Split up our cache texture into lines of certain widths
- int nextLine = 0;
+ int32_t nextLine = 0;
mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0));
nextLine += mCacheLines.top()->mMaxHeight;
mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
@@ -519,8 +590,8 @@
// Four verts, two triangles , six indices per quad
for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) {
- int i6 = i * 6;
- int i4 = i * 4;
+ int32_t i6 = i * 6;
+ int32_t i4 = i * 4;
indexPtr[i6 + 0] = i4 + 0;
indexPtr[i6 + 1] = i4 + 1;
@@ -713,7 +784,11 @@
}
-void FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, int numGlyphs, int x, int y)
+void FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y,
+ uint32_t startIndex, int32_t numGlyphs,
+ Font::RenderMode mode,
+ Font::Rect *bounds,
+ uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH)
{
checkInit();
@@ -730,7 +805,8 @@
return;
}
- currentFont->renderUTF(text, len, startIndex, numGlyphs, x, y);
+ currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs,
+ mode, bounds, bitmap, bitmapW, bitmapH);
if(mCurrentQuadIndex != 0) {
issueDrawCommand();
@@ -738,32 +814,8 @@
}
}
-void FontState::renderText(const char *text, int x, int y)
-{
- size_t textLen = strlen(text);
- renderText(text, textLen, 0, -1, x, y);
-}
-
-void FontState::renderText(Allocation *alloc, int x, int y)
-{
- if(!alloc) {
- return;
- }
-
- const char *text = (const char *)alloc->getPtr();
- size_t allocSize = alloc->getType()->getSizeBytes();
- renderText(text, allocSize, 0, -1, x, y);
-}
-
-void FontState::renderText(Allocation *alloc, uint32_t start, int len, int x, int y)
-{
- if(!alloc) {
- return;
- }
-
- const char *text = (const char *)alloc->getPtr();
- size_t allocSize = alloc->getType()->getSizeBytes();
- renderText(text, allocSize, start, len, x, y);
+void FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) {
+ renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds);
}
void FontState::setFontColor(float r, float g, float b, float a) {
@@ -773,7 +825,7 @@
mConstants.mFontColor[3] = a;
mConstants.mGamma = 1.0f;
- const int luminance = (r * 2.0f + g * 5.0f + b) / 8.0f;
+ const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f;
if (luminance <= mBlackThreshold) {
mConstants.mGamma = mBlackGamma;
} else if (luminance >= mWhiteThreshold) {
diff --git a/libs/rs/rsFont.h b/libs/rs/rsFont.h
index 16009ef..0012b84 100644
--- a/libs/rs/rsFont.h
+++ b/libs/rs/rsFont.h
@@ -45,12 +45,26 @@
class Font : public ObjectBase
{
public:
- ~Font();
+ enum RenderMode {
+ FRAMEBUFFER,
+ BITMAP,
+ MEASURE,
+ };
- // Pointer to the utf data, length of data, where to start, number of glyphs ot read
- // (each glyph may be longer than a char because we are dealing with utf data)
- // Last two variables are the initial pen position
- void renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyphs, int x, int y);
+ struct Rect {
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+ void set(int32_t l, int32_t r, int32_t t, int32_t b) {
+ left = l;
+ right = r;
+ top = t;
+ bottom = b;
+ }
+ };
+
+ ~Font();
// Currently files do not get serialized,
// but we need to inherit from ObjectBase for ref tracking
@@ -66,6 +80,14 @@
friend class FontState;
+ // Pointer to the utf data, length of data, where to start, number of glyphs ot read
+ // (each glyph may be longer than a char because we are dealing with utf data)
+ // Last two variables are the initial pen position
+ void renderUTF(const char *text, uint32_t len, int32_t x, int32_t y,
+ uint32_t start, int32_t numGlyphs,
+ RenderMode mode = FRAMEBUFFER, Rect *bounds = NULL,
+ uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0);
+
void invalidateTextureCache();
struct CachedGlyphInfo
{
@@ -106,7 +128,10 @@
CachedGlyphInfo *cacheGlyph(uint32_t glyph);
void updateGlyphCache(CachedGlyphInfo *glyph);
- void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
+ void measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds);
+ void drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y);
+ void drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y,
+ uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
};
class FontState
@@ -121,10 +146,13 @@
ObjectBaseRef<Font> mDefault;
ObjectBaseRef<Font> mLast;
- void renderText(const char *text, uint32_t len, uint32_t startIndex, int numGlyphs, int x, int y);
- void renderText(const char *text, int x, int y);
- void renderText(Allocation *alloc, int x, int y);
- void renderText(Allocation *alloc, uint32_t start, int len, int x, int y);
+ void renderText(const char *text, uint32_t len, int32_t x, int32_t y,
+ uint32_t startIndex = 0, int numGlyphs = -1,
+ Font::RenderMode mode = Font::FRAMEBUFFER,
+ Font::Rect *bounds = NULL,
+ uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0);
+
+ void measureText(const char *text, uint32_t len, Font::Rect *bounds);
void setFontColor(float r, float g, float b, float a);
void getFontColor(float *r, float *g, float *b, float *a) const;
@@ -198,6 +226,9 @@
// Texture to cache glyph bitmaps
ObjectBaseRef<Allocation> mTextTexture;
void initTextTexture();
+ const uint8_t* getTextTextureData() const {
+ return (uint8_t*)mTextTexture->getPtr();
+ }
bool cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY);
const Type* getCacheTextureType() {
diff --git a/libs/rs/rsLight.cpp b/libs/rs/rsLight.cpp
deleted file mode 100644
index eab9a07..0000000
--- a/libs/rs/rsLight.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef ANDROID_RS_BUILD_FOR_HOST
-#include "rsContext.h"
-#include <GLES/gl.h>
-#else
-#include "rsContextHostStub.h"
-#include <OpenGL/gl.h>
-#endif //ANDROID_RS_BUILD_FOR_HOST
-
-using namespace android;
-using namespace android::renderscript;
-
-
-Light::Light(Context *rsc, bool isLocal, bool isMono) : ObjectBase(rsc)
-{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
- mIsLocal = isLocal;
- mIsMono = isMono;
-
- mPosition[0] = 0;
- mPosition[1] = 0;
- mPosition[2] = 1;
- mPosition[3] = 0;
-
- mColor[0] = 1.f;
- mColor[1] = 1.f;
- mColor[2] = 1.f;
- mColor[3] = 1.f;
-}
-
-Light::~Light()
-{
-}
-
-void Light::setPosition(float x, float y, float z)
-{
- mPosition[0] = x;
- mPosition[1] = y;
- mPosition[2] = z;
-}
-
-void Light::setColor(float r, float g, float b)
-{
- mColor[0] = r;
- mColor[1] = g;
- mColor[2] = b;
-}
-
-void Light::setupGL(uint32_t num) const
-{
- glLightfv(GL_LIGHT0 + num, GL_DIFFUSE, mColor);
- glLightfv(GL_LIGHT0 + num, GL_SPECULAR, mColor);
- glLightfv(GL_LIGHT0 + num, GL_POSITION, mPosition);
-}
-
-void Light::serialize(OStream *stream) const
-{
-
-}
-
-Light *Light::createFromStream(Context *rsc, IStream *stream)
-{
- return NULL;
-}
-
-////////////////////////////////////////////
-
-LightState::LightState()
-{
- clear();
-}
-
-LightState::~LightState()
-{
-}
-
-void LightState::clear()
-{
- mIsLocal = false;
- mIsMono = false;
-}
-
-
-////////////////////////////////////////////////////
-//
-
-namespace android {
-namespace renderscript {
-
-void rsi_LightBegin(Context *rsc)
-{
- rsc->mStateLight.clear();
-}
-
-void rsi_LightSetLocal(Context *rsc, bool isLocal)
-{
- rsc->mStateLight.mIsLocal = isLocal;
-}
-
-void rsi_LightSetMonochromatic(Context *rsc, bool isMono)
-{
- rsc->mStateLight.mIsMono = isMono;
-}
-
-RsLight rsi_LightCreate(Context *rsc)
-{
- Light *l = new Light(rsc, rsc->mStateLight.mIsLocal,
- rsc->mStateLight.mIsMono);
- l->incUserRef();
- return l;
-}
-
-void rsi_LightSetColor(Context *rsc, RsLight vl, float r, float g, float b)
-{
- Light *l = static_cast<Light *>(vl);
- l->setColor(r, g, b);
-}
-
-void rsi_LightSetPosition(Context *rsc, RsLight vl, float x, float y, float z)
-{
- Light *l = static_cast<Light *>(vl);
- l->setPosition(x, y, z);
-}
-
-
-
-}
-}
diff --git a/libs/rs/rsLight.h b/libs/rs/rsLight.h
deleted file mode 100644
index bd58979..0000000
--- a/libs/rs/rsLight.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef ANDROID_LIGHT_H
-#define ANDROID_LIGHT_H
-
-
-#include "rsObjectBase.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-namespace renderscript {
-
-
-// An element is a group of Components that occupies one cell in a structure.
-class Light : public ObjectBase
-{
-public:
- Light(Context *, bool isLocal, bool isMono);
- virtual ~Light();
-
- // Values, mutable after creation.
- void setPosition(float x, float y, float z);
- void setColor(float r, float g, float b);
-
- void setupGL(uint32_t num) const;
- virtual void serialize(OStream *stream) const;
- virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_LIGHT; }
- static Light *createFromStream(Context *rsc, IStream *stream);
-
-protected:
- float mColor[4];
- float mPosition[4];
- bool mIsLocal;
- bool mIsMono;
-};
-
-
-class LightState {
-public:
- LightState();
- ~LightState();
-
- void clear();
-
- bool mIsMono;
- bool mIsLocal;
-};
-
-
-}
-}
-#endif //ANDROID_LIGHT_H
-
diff --git a/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp
index 88db761..b991cab 100644
--- a/libs/rs/rsScriptC_LibGL.cpp
+++ b/libs/rs/rsScriptC_LibGL.cpp
@@ -351,13 +351,59 @@
CHECK_OBJ(va);
GET_TLS();
Allocation *alloc = static_cast<Allocation *>(va);
- rsc->mStateFont.renderText(alloc, x, y);
+ const char *text = (const char *)alloc->getPtr();
+ size_t allocSize = alloc->getType()->getSizeBytes();
+ rsc->mStateFont.renderText(text, allocSize, x, y);
}
static void SC_DrawText(const char *text, int x, int y)
{
GET_TLS();
- rsc->mStateFont.renderText(text, x, y);
+ size_t textLen = strlen(text);
+ rsc->mStateFont.renderText(text, textLen, x, y);
+}
+
+static void SC_setMetrics(Font::Rect *metrics,
+ int32_t *left, int32_t *right,
+ int32_t *top, int32_t *bottom)
+{
+ if(left) {
+ *left = metrics->left;
+ }
+ if(right) {
+ *right = metrics->right;
+ }
+ if(top) {
+ *top = metrics->top;
+ }
+ if(bottom) {
+ *bottom = metrics->bottom;
+ }
+}
+
+static void SC_MeasureTextAlloc(RsAllocation va,
+ int32_t *left, int32_t *right,
+ int32_t *top, int32_t *bottom)
+{
+ CHECK_OBJ(va);
+ GET_TLS();
+ Allocation *alloc = static_cast<Allocation *>(va);
+ const char *text = (const char *)alloc->getPtr();
+ size_t textLen = alloc->getType()->getSizeBytes();
+ Font::Rect metrics;
+ rsc->mStateFont.measureText(text, textLen, &metrics);
+ SC_setMetrics(&metrics, left, right, top, bottom);
+}
+
+static void SC_MeasureText(const char *text,
+ int32_t *left, int32_t *right,
+ int32_t *top, int32_t *bottom)
+{
+ GET_TLS();
+ size_t textLen = strlen(text);
+ Font::Rect metrics;
+ rsc->mStateFont.measureText(text, textLen, &metrics);
+ SC_setMetrics(&metrics, left, right, top, bottom);
}
static void SC_BindFont(RsFont font)
@@ -432,6 +478,8 @@
{ "_Z11rsgDrawTextPKcii", (void *)&SC_DrawText },
{ "_Z11rsgDrawText13rs_allocationii", (void *)&SC_DrawTextAlloc },
+ { "_Z14rsgMeasureTextPKcPiS1_S1_S1_", (void *)&SC_MeasureText },
+ { "_Z14rsgMeasureText13rs_allocationPiS0_S0_S0_", (void *)&SC_MeasureTextAlloc },
{ "_Z11rsgBindFont7rs_font", (void *)&SC_BindFont },
{ "_Z12rsgFontColorffff", (void *)&SC_FontColor },
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index fc037a3..8cdb48a 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -274,6 +274,59 @@
return false;
}
+Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const
+{
+ TypeState * stc = &rsc->mStateType;
+ for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
+ Type *t = stc->mTypes[ct];
+ if (t->getElement() != mElement.get()) continue;
+ if (t->getDimX() != dimX) continue;
+ if (t->getDimY() != mDimY) continue;
+ if (t->getDimZ() != mDimZ) continue;
+ if (t->getDimLOD() != mDimLOD) continue;
+ if (t->getDimFaces() != mFaces) continue;
+ t->incUserRef();
+ return t;
+ }
+
+ Type *nt = new Type(rsc);
+ nt->mElement.set(mElement);
+ nt->mDimX = dimX;
+ nt->mDimY = mDimY;
+ nt->mDimZ = mDimZ;
+ nt->mDimLOD = mDimLOD;
+ nt->mFaces = mFaces;
+ nt->compute();
+ return nt;
+}
+
+Type * Type::cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const
+{
+ TypeState * stc = &rsc->mStateType;
+ for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
+ Type *t = stc->mTypes[ct];
+ if (t->getElement() != mElement.get()) continue;
+ if (t->getDimX() != dimX) continue;
+ if (t->getDimY() != dimY) continue;
+ if (t->getDimZ() != mDimZ) continue;
+ if (t->getDimLOD() != mDimLOD) continue;
+ if (t->getDimFaces() != mFaces) continue;
+ t->incUserRef();
+ return t;
+ }
+
+ Type *nt = new Type(rsc);
+ nt->mElement.set(mElement);
+ nt->mDimX = dimX;
+ nt->mDimY = dimY;
+ nt->mDimZ = mDimZ;
+ nt->mDimLOD = mDimLOD;
+ nt->mFaces = mFaces;
+ nt->compute();
+ return nt;
+}
+
+
//////////////////////////////////////////////////
//
namespace android {
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 33faa87..b5548c0 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -79,6 +79,9 @@
bool isEqual(const Type *other) const;
+ Type * cloneAndResize1D(Context *rsc, uint32_t dimX) const;
+ Type * cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const;
+
protected:
struct LOD {
size_t mX;
diff --git a/libs/rs/rsVertexArray.h b/libs/rs/rsVertexArray.h
index bd76d87..dea7d41 100644
--- a/libs/rs/rsVertexArray.h
+++ b/libs/rs/rsVertexArray.h
@@ -62,7 +62,6 @@
}
void add(const Attrib &, uint32_t stride);
- //void addLegacy(uint32_t type, uint32_t size, uint32_t stride, bool normalized, uint32_t offset);
void add(uint32_t type, uint32_t size, uint32_t stride, bool normalized, uint32_t offset, const char *name);
void setupGL2(const Context *rsc, class VertexArrayState *, ShaderCache *) const;
@@ -89,7 +88,7 @@
}
}
-#endif //ANDROID_LIGHT_H
+#endif //ANDROID_VERTEX_ARRAY_H
diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh
index c0b2d2d..ac6f8cc 100644
--- a/libs/rs/scriptc/rs_graphics.rsh
+++ b/libs/rs/scriptc/rs_graphics.rsh
@@ -79,6 +79,12 @@
rsgBindFont(rs_font);
extern void __attribute__((overloadable))
rsgFontColor(float, float, float, float);
+// Returns the bounding box of the text relative to (0, 0)
+// Any of left, right, top, bottom could be NULL
+extern void __attribute__((overloadable))
+ rsgMeasureText(const char *, int *left, int *right, int *top, int *bottom);
+extern void __attribute__((overloadable))
+ rsgMeasureText(rs_allocation, int *left, int *right, int *top, int *bottom);
extern void __attribute__((overloadable))
rsgMeshComputeBoundingBox(rs_mesh mesh, float *minX, float *minY, float *minZ,
diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java
index 3b800f2..8da7eaa 100755
--- a/media/java/android/media/videoeditor/AudioTrack.java
+++ b/media/java/android/media/videoeditor/AudioTrack.java
@@ -32,14 +32,15 @@
// Instance variables
private final String mUniqueId;
private final String mFilename;
- private final long mDurationMs;
private long mStartTimeMs;
private long mTimelineDurationMs;
private int mVolumePercent;
private long mBeginBoundaryTimeMs;
private long mEndBoundaryTimeMs;
private boolean mLoop;
+ private boolean mMuted;
+ private final long mDurationMs;
private final int mAudioChannels;
private final int mAudioType;
private final int mAudioBitrate;
@@ -217,6 +218,9 @@
// By default loop is disabled
mLoop = false;
+ // By default the audio track is not muted
+ mMuted = false;
+
// Ducking is enabled by default
mDuckingThreshold = 0;
mDuckingLowVolume = 0;
@@ -239,12 +243,13 @@
* beginning of the audio track)
* @param loop true to loop the audio track
* @param volume The volume in percentage
+ * @param muted true if the audio track is muted
* @param audioWaveformFilename The name of the waveform file
*
* @throws IOException if file is not found
*/
AudioTrack(String audioTrackId, String filename, long startTimeMs, long beginMs, long endMs,
- boolean loop, int volume, String audioWaveformFilename) throws IOException {
+ boolean loop, int volume, boolean muted, String audioWaveformFilename) throws IOException {
mUniqueId = audioTrackId;
mFilename = filename;
mStartTimeMs = startTimeMs;
@@ -266,6 +271,7 @@
mEndBoundaryTimeMs = endMs;
mLoop = loop;
+ mMuted = muted;
mAudioWaveformFilename = audioWaveformFilename;
}
@@ -341,6 +347,20 @@
}
/**
+ * @param muted true to mute the audio track
+ */
+ public void setMute(boolean muted) {
+ mMuted = muted;
+ }
+
+ /**
+ * @return true if the audio track is muted
+ */
+ public boolean isMuted() {
+ return mMuted;
+ }
+
+ /**
* Set the start time of this audio track relative to the storyboard
* timeline. Default value is 0.
*
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index 13014a7..cc0a155 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -49,6 +49,7 @@
private long mBeginBoundaryTimeMs;
private long mEndBoundaryTimeMs;
private int mVolumePercentage;
+ private boolean mMuted;
private String mAudioWaveformFilename;
private PlaybackThread mPlaybackThread;
@@ -206,7 +207,7 @@
*/
public MediaVideoItem(String mediaItemId, String filename, int renderingMode)
throws IOException {
- this(mediaItemId, filename, renderingMode, null);
+ this(mediaItemId, filename, renderingMode, 0, END_OF_FILE, 100, false, null);
}
/**
@@ -215,11 +216,19 @@
* @param mediaItemId The MediaItem id
* @param filename The image file name
* @param renderingMode The rendering mode
+ * @param beginMs Start time in milliseconds. Set to 0 to extract from the
+ * beginning
+ * @param endMs End time in milliseconds. Set to {@link #END_OF_FILE} to
+ * extract until the end
+ * @param volumePercent in %/. 100% means no change; 50% means half value, 200%
+ * means double, 0% means silent.
+ * @param muted true if the audio is muted
* @param audioWaveformFilename The name of the audio waveform file
*
* @throws IOException if the file cannot be opened for reading
*/
MediaVideoItem(String mediaItemId, String filename, int renderingMode,
+ long beginMs, long endMs, int volumePercent, boolean muted,
String audioWaveformFilename) throws IOException {
super(mediaItemId, filename, renderingMode);
// TODO: Set these variables correctly
@@ -239,9 +248,10 @@
mAudioChannels = 2;
mAudioSamplingFrequency = 16000;
- mBeginBoundaryTimeMs = 0;
- mEndBoundaryTimeMs = mDurationMs;
- mVolumePercentage = 100;
+ mBeginBoundaryTimeMs = beginMs;
+ mEndBoundaryTimeMs = endMs == END_OF_FILE ? mDurationMs : endMs;
+ mVolumePercentage = volumePercent;
+ mMuted = muted;
mAudioWaveformFilename = audioWaveformFilename;
}
@@ -539,6 +549,20 @@
}
/**
+ * @param muted true to mute the media item
+ */
+ public void setMute(boolean muted) {
+ mMuted = muted;
+ }
+
+ /**
+ * @return true if the media item is muted
+ */
+ public boolean isMuted() {
+ return mMuted;
+ }
+
+ /**
* @return The video type
*/
public int getVideoType() {
diff --git a/media/java/android/media/videoeditor/VideoEditorTestImpl.java b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
index de962e89..b39d9d8 100644
--- a/media/java/android/media/videoeditor/VideoEditorTestImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
@@ -89,6 +89,7 @@
private static final String ATTR_END_RECT_R = "end_r";
private static final String ATTR_END_RECT_B = "end_b";
private static final String ATTR_LOOP = "loop";
+ private static final String ATTR_MUTED = "muted";
// Instance variables
private long mDurationMs;
@@ -582,6 +583,7 @@
.attribute("", ATTR_BEGIN_TIME, Long.toString(mvi.getBoundaryBeginTime()));
serializer.attribute("", ATTR_END_TIME, Long.toString(mvi.getBoundaryEndTime()));
serializer.attribute("", ATTR_VOLUME, Integer.toString(mvi.getVolume()));
+ serializer.attribute("", ATTR_MUTED, Boolean.toString(mvi.isMuted()));
if (mvi.getAudioWaveformFilename() != null) {
serializer.attribute("", ATTR_AUDIO_WAVEFORM_FILENAME,
mvi.getAudioWaveformFilename());
@@ -713,6 +715,7 @@
serializer.attribute("", ATTR_BEGIN_TIME, Long.toString(at.getBoundaryBeginTime()));
serializer.attribute("", ATTR_END_TIME, Long.toString(at.getBoundaryEndTime()));
serializer.attribute("", ATTR_VOLUME, Integer.toString(at.getVolume()));
+ serializer.attribute("", ATTR_MUTED, Boolean.toString(at.isMuted()));
serializer.attribute("", ATTR_LOOP, Boolean.toString(at.isLooping()));
if (at.getAudioWaveformFilename() != null) {
serializer.attribute("", ATTR_AUDIO_WAVEFORM_FILENAME,
@@ -765,10 +768,19 @@
currentMediaItem = new MediaImageItem(mediaItemId, filename,
durationMs, renderingMode);
} else if (MediaVideoItem.class.getSimpleName().equals(type)) {
+ final long beginMs = Long.parseLong(parser.getAttributeValue("",
+ ATTR_BEGIN_TIME));
+ final long endMs = Long.parseLong(parser.getAttributeValue("",
+ ATTR_END_TIME));
+ final int volume = Integer.parseInt(parser.getAttributeValue("",
+ ATTR_VOLUME));
+ final boolean muted = Boolean.parseBoolean(parser.getAttributeValue("",
+ ATTR_MUTED));
final String audioWaveformFilename = parser.getAttributeValue("",
ATTR_AUDIO_WAVEFORM_FILENAME);
currentMediaItem = new MediaVideoItem(mediaItemId, filename,
- renderingMode, audioWaveformFilename);
+ renderingMode, beginMs, endMs, volume, muted,
+ audioWaveformFilename);
final long beginTimeMs = Long.parseLong(parser.getAttributeValue("",
ATTR_BEGIN_TIME));
@@ -1001,11 +1013,12 @@
final long beginMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
final long endMs = Long.parseLong(parser.getAttributeValue("", ATTR_END_TIME));
final int volume = Integer.parseInt(parser.getAttributeValue("", ATTR_VOLUME));
+ final boolean muted = Boolean.parseBoolean(parser.getAttributeValue("", ATTR_MUTED));
final boolean loop = Boolean.parseBoolean(parser.getAttributeValue("", ATTR_LOOP));
final String waveformFilename = parser.getAttributeValue("", ATTR_AUDIO_WAVEFORM_FILENAME);
try {
final AudioTrack audioTrack = new AudioTrack(audioTrackId, filename, startTimeMs,
- beginMs, endMs, loop, volume, waveformFilename);
+ beginMs, endMs, loop, volume, muted, waveformFilename);
return audioTrack;
} catch (IOException ex) {
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 546df47..90b1aab 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -40,6 +40,7 @@
static const int64_t kMax32BitFileSize = 0x007fffffffLL;
static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
static const uint8_t kNalUnitTypePicParamSet = 0x08;
+static const int64_t kVideoMediaTimeAdjustPeriodTimeUs = 10000000LL; // 10s
class MPEG4Writer::Track {
public:
@@ -148,6 +149,28 @@
int64_t mPreviousTrackTimeUs;
int64_t mTrackEveryTimeDurationUs;
+ // Has the media time adjustment for video started?
+ bool mIsMediaTimeAdjustmentOn;
+ // The time stamp when previous media time adjustment period starts
+ int64_t mPrevMediaTimeAdjustTimestampUs;
+ // Number of vidoe frames whose time stamp may be adjusted
+ int64_t mMediaTimeAdjustNumFrames;
+ // The sample number when previous meida time adjustmnet period starts
+ int64_t mPrevMediaTimeAdjustSample;
+ // The total accumulated drift time within a period of
+ // kVideoMediaTimeAdjustPeriodTimeUs.
+ int64_t mTotalDriftTimeToAdjustUs;
+ // The total accumalated drift time since the start of the recording
+ // excluding the current time adjustment period
+ int64_t mPrevTotalAccumDriftTimeUs;
+
+ // Update the audio track's drift information.
+ void updateDriftTime(const sp<MetaData>& meta);
+
+ // Adjust the time stamp of the video track according to
+ // the drift time information from the audio track.
+ void adjustMediaTime(int64_t *timestampUs);
+
static void *ThreadWrapper(void *me);
status_t threadEntry();
@@ -319,7 +342,7 @@
size = MAX_MOOV_BOX_SIZE;
}
- LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
+ LOGV("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
" moov size %lld bytes",
mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
return factor * size;
@@ -346,7 +369,7 @@
// If file size is set to be larger than the 32 bit file
// size limit, treat it as an error.
if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
- LOGW("32-bi file size limit (%lld bytes) too big. "
+ LOGW("32-bit file size limit (%lld bytes) too big. "
"It is changed to %lld bytes",
mMaxFileSizeLimitBytes, kMax32BitFileSize);
mMaxFileSizeLimitBytes = kMax32BitFileSize;
@@ -1149,6 +1172,12 @@
mNumStscTableEntries = 0;
mNumSttsTableEntries = 0;
mMdatSizeBytes = 0;
+ mIsMediaTimeAdjustmentOn = false;
+ mPrevMediaTimeAdjustTimestampUs = 0;
+ mMediaTimeAdjustNumFrames = 0;
+ mPrevMediaTimeAdjustSample = 0;
+ mTotalDriftTimeToAdjustUs = 0;
+ mPrevTotalAccumDriftTimeUs = 0;
pthread_create(&mThread, &attr, ThreadWrapper, this);
pthread_attr_destroy(&attr);
@@ -1437,6 +1466,145 @@
return OK;
}
+/*
+* The video track's media time adjustment for real-time applications
+* is described as follows:
+*
+* First, the media time adjustment is done for every period of
+* kVideoMediaTimeAdjustPeriodTimeUs. kVideoMediaTimeAdjustPeriodTimeUs
+* is currently a fixed value chosen heuristically. The value of
+* kVideoMediaTimeAdjustPeriodTimeUs should not be very large or very small
+* for two considerations: on one hand, a relatively large value
+* helps reduce large fluctuation of drift time in the audio encoding
+* path; while on the other hand, a relatively small value helps keep
+* restoring synchronization in audio/video more frequently. Note for the
+* very first period of kVideoMediaTimeAdjustPeriodTimeUs, there is
+* no media time adjustment for the video track.
+*
+* Second, the total accumulated audio track time drift found
+* in a period of kVideoMediaTimeAdjustPeriodTimeUs is distributed
+* over a stream of incoming video frames. The number of video frames
+* affected is determined based on the number of recorded video frames
+* within the past kVideoMediaTimeAdjustPeriodTimeUs period.
+* We choose to distribute the drift time over only a portion
+* (rather than all) of the total number of recorded video frames
+* in order to make sure that the video track media time adjustment is
+* completed for the current period before the next video track media
+* time adjustment period starts. Currently, the portion chosen is a
+* half (0.5).
+*
+* Last, various additional checks are performed to ensure that
+* the actual audio encoding path does not have too much drift.
+* In particular, 1) we want to limit the average incremental time
+* adjustment for each video frame to be less than a threshold
+* for a single period of kVideoMediaTimeAdjustPeriodTimeUs.
+* Currently, the threshold is set to 5 ms. If the average incremental
+* media time adjustment for a video frame is larger than the
+* threshold, the audio encoding path has too much time drift.
+* 2) We also want to limit the total time drift in the audio
+* encoding path to be less than a threshold for a period of
+* kVideoMediaTimeAdjustPeriodTimeUs. Currently, the threshold
+* is 0.5% of kVideoMediaTimeAdjustPeriodTimeUs. If the time drift of
+* the audio encoding path is larger than the threshold, the audio
+* encoding path has too much time drift. We treat the large time
+* drift of the audio encoding path as errors, since there is no
+* way to keep audio/video in synchronization for real-time
+* applications if the time drift is too large unless we drop some
+* video frames, which has its own problems that we don't want
+* to get into for the time being.
+*/
+void MPEG4Writer::Track::adjustMediaTime(int64_t *timestampUs) {
+ if (*timestampUs - mPrevMediaTimeAdjustTimestampUs >=
+ kVideoMediaTimeAdjustPeriodTimeUs) {
+
+ LOGV("New media time adjustment period at %lld us", *timestampUs);
+ mIsMediaTimeAdjustmentOn = true;
+ mMediaTimeAdjustNumFrames =
+ (mNumSamples - mPrevMediaTimeAdjustSample) >> 1;
+
+ mPrevMediaTimeAdjustTimestampUs = *timestampUs;
+ mPrevMediaTimeAdjustSample = mNumSamples;
+ int64_t totalAccumDriftTimeUs = mOwner->getDriftTimeUs();
+ mTotalDriftTimeToAdjustUs =
+ totalAccumDriftTimeUs - mPrevTotalAccumDriftTimeUs;
+
+ mPrevTotalAccumDriftTimeUs = totalAccumDriftTimeUs;
+
+ // Check on incremental adjusted time per frame
+ int64_t adjustTimePerFrameUs =
+ mTotalDriftTimeToAdjustUs / mMediaTimeAdjustNumFrames;
+
+ if (adjustTimePerFrameUs < 0) {
+ adjustTimePerFrameUs = -adjustTimePerFrameUs;
+ }
+ if (adjustTimePerFrameUs >= 5000) {
+ LOGE("Adjusted time per video frame is %lld us",
+ adjustTimePerFrameUs);
+ CHECK(!"Video frame time adjustment is too large!");
+ }
+
+ // Check on total accumulated time drift within a period of
+ // kVideoMediaTimeAdjustPeriodTimeUs.
+ int64_t driftPercentage = (mTotalDriftTimeToAdjustUs * 1000)
+ / kVideoMediaTimeAdjustPeriodTimeUs;
+
+ if (driftPercentage < 0) {
+ driftPercentage = -driftPercentage;
+ }
+ if (driftPercentage > 5) {
+ LOGE("Audio track has time drift %lld us over %lld us",
+ mTotalDriftTimeToAdjustUs,
+ kVideoMediaTimeAdjustPeriodTimeUs);
+
+ CHECK(!"The audio track media time drifts too much!");
+ }
+
+ }
+
+ if (mIsMediaTimeAdjustmentOn) {
+ if (mNumSamples - mPrevMediaTimeAdjustSample <=
+ mMediaTimeAdjustNumFrames) {
+
+ // Do media time incremental adjustment
+ int64_t incrementalAdjustTimeUs =
+ (mTotalDriftTimeToAdjustUs *
+ (mNumSamples - mPrevMediaTimeAdjustSample))
+ / mMediaTimeAdjustNumFrames;
+
+ *timestampUs +=
+ (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs);
+
+ LOGV("Incremental video frame media time adjustment: %lld us",
+ (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs));
+ } else {
+ // Within the remaining adjustment period,
+ // no incremental adjustment is needed.
+ *timestampUs +=
+ (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs);
+
+ LOGV("Fixed video frame media time adjustment: %lld us",
+ (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs));
+ }
+ }
+}
+
+/*
+ * Updates the drift time from the audio track so that
+ * the video track can get the updated drift time information
+ * from the file writer. The fluctuation of the drift time of the audio
+ * encoding path is smoothed out with a simple filter by giving a larger
+ * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
+ * are heuristically determined.
+ */
+void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
+ int64_t driftTimeUs = 0;
+ if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
+ int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
+ int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
+ mOwner->setDriftTimeUs(timeUs);
+ }
+}
+
status_t MPEG4Writer::Track::threadEntry() {
int32_t count = 0;
const int64_t interleaveDurationUs = mOwner->interleaveDuration();
@@ -1587,24 +1755,16 @@
timestampUs -= previousPausedDurationUs;
CHECK(timestampUs >= 0);
- if (mIsRealTimeRecording && !mIsAudio) {
- // The minor adjustment on the timestamp is heuristic/experimental
- // We are adjusting the timestamp to reduce the fluctuation of the duration
- // of neighboring samples. This in turn helps reduce the track header size,
- // especially, the number of entries in the "stts" box.
- if (mNumSamples > 1) {
- int64_t currDriftTimeUs = mOwner->getDriftTimeUs();
- int64_t durationUs = timestampUs + currDriftTimeUs - lastTimestampUs;
- int64_t diffUs = (durationUs > lastDurationUs)
- ? durationUs - lastDurationUs
- : lastDurationUs - durationUs;
- if (diffUs <= 5000) { // XXX: Magic number 5ms
- timestampUs = lastTimestampUs + lastDurationUs;
- } else {
- timestampUs += currDriftTimeUs;
- }
+
+ // Media time adjustment for real-time applications
+ if (mIsRealTimeRecording) {
+ if (mIsAudio) {
+ updateDriftTime(meta_data);
+ } else {
+ adjustMediaTime(×tampUs);
}
}
+
CHECK(timestampUs >= 0);
if (mNumSamples > 1) {
if (timestampUs <= lastTimestampUs) {
@@ -1656,12 +1816,6 @@
lastDurationUs = timestampUs - lastTimestampUs;
lastDurationTicks = currDurationTicks;
lastTimestampUs = timestampUs;
- if (mIsRealTimeRecording && mIsAudio) {
- int64_t driftTimeUs = 0;
- if (meta_data->findInt64(kKeyDriftTime, &driftTimeUs)) {
- mOwner->setDriftTimeUs(driftTimeUs);
- }
- }
if (isSync != 0) {
addOneStssTableEntry(mNumSamples);
@@ -1735,6 +1889,9 @@
mReachedEOS = true;
LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
+ if (mIsAudio) {
+ LOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
+ }
if (err == ERROR_END_OF_STREAM) {
return OK;
diff --git a/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png b/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
index d894f7b..e74c22f 100644
--- a/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
+++ b/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
index 744178f..d6c8a21 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
index 3e317dd..b16e436 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
index 2f66b1d..b16e436 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
index 72329f8..1b6ed74 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
index 72329f8..43e35d3 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
index 558c49c..498adbb 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
index 558c49c..b7e42a0 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
index 6440bdd..959fc5c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
index 6440bdd..f905979 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
index fe20423..6e8e73c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
index fe20423..b5799c8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
new file mode 100644
index 0000000..a0def6b
--- /dev/null
+++ b/packages/SystemUI/res/values/colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <drawable name="notification_number_text_color">#ffffffff</drawable>
+</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/IconMerger.java b/packages/SystemUI/src/com/android/systemui/statusbar/IconMerger.java
index 027bed4a..e87d003 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/IconMerger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/IconMerger.java
@@ -23,28 +23,34 @@
import android.view.View;
import android.widget.LinearLayout;
+import com.android.internal.statusbar.StatusBarIcon;
+
import com.android.systemui.R;
public class IconMerger extends LinearLayout {
private static final String TAG = "IconMerger";
+ private int mIconSize;
private StatusBarIconView mMoreView;
+ private StatusBarIcon mMoreIcon = new StatusBarIcon(null, R.drawable.stat_notify_more, 0);
public IconMerger(Context context, AttributeSet attrs) {
super(context, attrs);
+
+ mIconSize = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_icon_size);
+
+ mMoreView = new StatusBarIconView(context, "more");
+ mMoreView.set(mMoreIcon);
+ addView(mMoreView, 0, new LinearLayout.LayoutParams(mIconSize, mIconSize));
}
- public void addMoreView(StatusBarIconView v, LinearLayout.LayoutParams lp) {
- super.addView(v, lp);
- mMoreView = v;
- }
-
- public void addView(StatusBarIconView v, int index, LinearLayout.LayoutParams lp) {
+ public void addView(StatusBarIconView v, int index) {
if (index == 0) {
throw new RuntimeException("Attempt to put view before the more view: " + v);
}
- super.addView(v, index, lp);
+ addView(v, index, new LinearLayout.LayoutParams(mIconSize, mIconSize));
}
@Override
@@ -127,28 +133,8 @@
}
}
}
-
- // BUG: Updating the text during the layout here doesn't seem to cause
- // the view to be redrawn fully. The text view gets resized correctly, but the
- // text contents aren't drawn properly. To work around this, we post a message
- // and provide the value later. We're the only one changing this value show it
- // should be ordered correctly.
- if (false) {
- // TODO this.moreIcon.update(number);
- } else {
- mBugWorkaroundNumber = number;
- mBugWorkaroundHandler.post(mBugWorkaroundRunnable);
- }
- }
- private int mBugWorkaroundNumber;
- private Handler mBugWorkaroundHandler = new Handler();
- private Runnable mBugWorkaroundRunnable = new Runnable() {
- public void run() {
- /* TODO
- IconMerger.this.moreIcon.update(mBugWorkaroundNumber);
- IconMerger.this.moreIcon.view.invalidate();
- */
- }
- };
+ mMoreIcon.number = number;
+ mMoreView.set(mMoreIcon);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
index e945981..57ebd27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
@@ -274,12 +274,6 @@
mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
- // the more notifications icon
- StatusBarIconView moreView = new StatusBarIconView(this, "more");
- moreView.set(new StatusBarIcon(null, R.drawable.stat_notify_more, 0));
- mNotificationIcons.addMoreView(moreView,
- new LinearLayout.LayoutParams(mIconSize, mIconSize));
-
// set the inital view visibility
setAreThereNotifications();
mDateView.setVisibility(View.INVISIBLE);
@@ -579,8 +573,7 @@
parent.addView(row, viewIndex);
// Add the icon.
final int iconIndex = chooseIconIndex(isOngoing, viewIndex);
- mNotificationIcons.addView(iconView, iconIndex,
- new LinearLayout.LayoutParams(mIconSize, mIconSize));
+ mNotificationIcons.addView(iconView, iconIndex);
return iconView;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 0ca0572..8419e56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -21,22 +21,37 @@
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
import android.util.Slog;
import android.util.Log;
+import android.view.View;
import android.view.ViewDebug;
import android.widget.FrameLayout;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.R;
+
public class StatusBarIconView extends AnimatedImageView {
private static final String TAG = "StatusBarIconView";
private StatusBarIcon mIcon;
@ViewDebug.ExportedProperty private String mSlot;
+ private Drawable mNumberBackground;
+ private Paint mNumberPain;
+ private int mNumberX;
+ private int mNumberY;
+ private String mNumberText;
public StatusBarIconView(Context context, String slot) {
super(context);
+ final Resources res = context.getResources();
mSlot = slot;
+ mNumberPain = new Paint();
+ mNumberPain.setTextAlign(Paint.Align.CENTER);
+ mNumberPain.setColor(res.getColor(R.drawable.notification_number_text_color));
+ mNumberPain.setAntiAlias(true);
}
private static boolean streq(String a, String b) {
@@ -63,6 +78,9 @@
&& mIcon.iconLevel == icon.iconLevel;
final boolean visibilityEquals = mIcon != null
&& mIcon.visible == icon.visible;
+ final boolean numberEquals = mIcon != null
+ && mIcon.number == icon.number;
+ mIcon = icon.clone();
if (!iconEquals) {
Drawable drawable = getIcon(icon);
if (drawable == null) {
@@ -74,10 +92,22 @@
if (!levelEquals) {
setImageLevel(icon.iconLevel);
}
+ if (!numberEquals) {
+ if (icon.number > 0) {
+ if (mNumberBackground == null) {
+ mNumberBackground = getContext().getResources().getDrawable(
+ R.drawable.ic_notification_overlay);
+ }
+ placeNumber();
+ } else {
+ mNumberBackground = null;
+ mNumberText = null;
+ }
+ invalidate();
+ }
if (!visibilityEquals) {
setVisibility(icon.visible ? VISIBLE : GONE);
}
- mIcon = icon.clone();
return true;
}
@@ -126,9 +156,47 @@
return mIcon;
}
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ if (mNumberBackground != null) {
+ placeNumber();
+ }
+ }
+
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (mNumberBackground != null) {
+ mNumberBackground.draw(canvas);
+ canvas.drawText(mNumberText, mNumberX, mNumberY, mNumberPain);
+ }
+ }
+
protected void debug(int depth) {
super.debug(depth);
Log.d("View", debugIndent(depth) + "slot=" + mSlot);
Log.d("View", debugIndent(depth) + "icon=" + mIcon);
}
+
+ void placeNumber() {
+ final String str = mNumberText = Integer.toString(mIcon.number);
+ final int w = getWidth();
+ final int h = getHeight();
+ final Rect r = new Rect();
+ mNumberPain.getTextBounds(str, 0, str.length(), r);
+ final int tw = r.right - r.left;
+ final int th = r.bottom - r.top;
+ mNumberBackground.getPadding(r);
+ int dw = r.left + tw + r.right;
+ if (dw < mNumberBackground.getMinimumWidth()) {
+ dw = mNumberBackground.getMinimumWidth();
+ }
+ mNumberX = w-r.right-((dw-r.right-r.left)/2);
+ int dh = r.top + th + r.bottom;
+ if (dh < mNumberBackground.getMinimumWidth()) {
+ dh = mNumberBackground.getMinimumWidth();
+ }
+ mNumberY = h-r.bottom-((dh-r.top-th-r.bottom)/2);
+ mNumberBackground.setBounds(w-dw, h-dh, w, h);
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index c70f5d4..33685ba 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -296,7 +296,8 @@
int mLandscapeRotation = -1; // default landscape rotation
int mSeascapeRotation = -1; // "other" landscape rotation, 180 degrees from mLandscapeRotation
- int mPortraitRotation = -1;
+ int mPortraitRotation = -1; // default portrait rotation
+ int mUpsideDownRotation = -1; // "other" portrait rotation
// Nothing to see here, move along...
int mFancyRotationAnimation;
@@ -364,26 +365,25 @@
boolean useSensorForOrientationLp(int appOrientation) {
// The app says use the sensor.
- if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
+ if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
return true;
}
// The user preference says we can rotate, and the app is willing to rotate.
- // Note we include SCREEN_ORIENTATION_LANDSCAPE since we can use the sensor to choose
- // between the two possible landscape rotations.
if (mAccelerometerDefault != 0 &&
(appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
- || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
- || appOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) {
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
return true;
}
- // We're in a dock that has a rotation affinity, an the app is willing to rotate.
+ // We're in a dock that has a rotation affinity, and the app is willing to rotate.
if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR)
|| (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) {
// Note we override the nosensor flag here.
if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
- || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
- || appOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
return true;
}
}
@@ -397,7 +397,10 @@
* screen is switched off.
*/
boolean needSensorRunningLp() {
- if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
+ if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
+ || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+ || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
+ || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
// If the application has explicitly requested to follow the
// orientation, then we need to turn the sensor or.
return true;
@@ -2133,21 +2136,42 @@
if (d.getWidth() > d.getHeight()) {
mPortraitRotation = Surface.ROTATION_90;
mLandscapeRotation = Surface.ROTATION_0;
+ mUpsideDownRotation = Surface.ROTATION_270;
mSeascapeRotation = Surface.ROTATION_180;
} else {
mPortraitRotation = Surface.ROTATION_0;
mLandscapeRotation = Surface.ROTATION_90;
+ mUpsideDownRotation = Surface.ROTATION_180;
mSeascapeRotation = Surface.ROTATION_270;
}
}
synchronized (mLock) {
- if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
- //always return portrait if orientation set to portrait
- return mPortraitRotation;
- } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
- return getCurrentLandscapeRotation(lastRotation);
+ switch (orientation) {
+ case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
+ //always return portrait if orientation set to portrait
+ return mPortraitRotation;
+ case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
+ //always return landscape if orientation set to landscape
+ return mLandscapeRotation;
+ case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
+ //always return portrait if orientation set to portrait
+ return mUpsideDownRotation;
+ case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
+ //always return seascape if orientation set to reverse landscape
+ return mSeascapeRotation;
+ case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
+ //return either landscape rotation based on the sensor
+ mOrientationListener.setAllow180Rotation(false);
+ return getCurrentLandscapeRotation(lastRotation);
+ case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
+ mOrientationListener.setAllow180Rotation(true);
+ return getCurrentPortraitRotation(lastRotation);
}
+
+ mOrientationListener.setAllow180Rotation(
+ orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
+
// case for nosensor meaning ignore sensor and consider only lid
// or orientation sensor disabled
//or case.unspecified
@@ -2167,18 +2191,15 @@
}
private int getCurrentLandscapeRotation(int lastRotation) {
- // landscape-only apps can take either landscape rotation
- if (useSensorForOrientationLp(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) {
- int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
- if (isLandscapeOrSeascape(sensorRotation)) {
- return sensorRotation;
- }
+ int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
+ if (isLandscapeOrSeascape(sensorRotation)) {
+ return sensorRotation;
}
// try to preserve the old rotation if it was landscape
if (isLandscapeOrSeascape(lastRotation)) {
return lastRotation;
}
- // default to one of the two landscape rotations
+ // default to one of the primary landscape rotation
return mLandscapeRotation;
}
@@ -2186,6 +2207,23 @@
return sensorRotation == mLandscapeRotation || sensorRotation == mSeascapeRotation;
}
+ private int getCurrentPortraitRotation(int lastRotation) {
+ int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
+ if (isAnyPortrait(sensorRotation)) {
+ return sensorRotation;
+ }
+ // try to preserve the old rotation if it was portrait
+ if (isAnyPortrait(lastRotation)) {
+ return lastRotation;
+ }
+ // default to one of the primary portrait rotations
+ return mPortraitRotation;
+ }
+
+ private boolean isAnyPortrait(int sensorRotation) {
+ return sensorRotation == mPortraitRotation || sensorRotation == mUpsideDownRotation;
+ }
+
public boolean detectSafeMode() {
try {
int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index a960097..fe306b3 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -342,7 +342,6 @@
if (toChannel == null) {
throw new IllegalArgumentException("toChannel must not be null.");
}
- Slog.d(TAG, "transferring touch focus");
return nativeTransferTouchFocus(fromChannel, toChannel);
}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index de28375..9a5423c 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -117,6 +117,7 @@
final Context mContext;
final Handler mHandler;
+ final InputMethodSettings mSettings;
final SettingsObserver mSettingsObserver;
final StatusBarManagerService mStatusBar;
final IWindowManager mIWindowManager;
@@ -126,13 +127,8 @@
// All known input methods. mMethodMap also serves as the global
// lock for this class.
- final ArrayList<InputMethodInfo> mMethodList
- = new ArrayList<InputMethodInfo>();
- final HashMap<String, InputMethodInfo> mMethodMap
- = new HashMap<String, InputMethodInfo>();
-
- final TextUtils.SimpleStringSplitter mStringColonSplitter
- = new TextUtils.SimpleStringSplitter(':');
+ final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
+ final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<String, InputMethodInfo>();
class SessionState {
final ClientState client;
@@ -483,27 +479,18 @@
mStatusBar = statusBar;
statusBar.setIconVisibility("ime", false);
+ // mSettings should be created before buildInputMethodListLocked
+ mSettings = new InputMethodSettings(context.getContentResolver(), mMethodMap, mMethodList);
buildInputMethodListLocked(mMethodList, mMethodMap);
+ mSettings.enableAllIMEsIfThereIsNoEnabledIME();
- final String enabledStr = Settings.Secure.getString(
- mContext.getContentResolver(),
- Settings.Secure.ENABLED_INPUT_METHODS);
- Slog.i(TAG, "Enabled input methods: " + enabledStr);
- final String defaultIme = Settings.Secure.getString(mContext
- .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
- if (enabledStr == null || TextUtils.isEmpty(defaultIme)) {
- Slog.i(TAG, "Enabled input methods or default IME has not been set, enabling all");
+ if (TextUtils.isEmpty(Settings.Secure.getString(
+ mContext.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD))) {
InputMethodInfo defIm = null;
- StringBuilder sb = new StringBuilder(256);
- final int N = mMethodList.size();
- for (int i=0; i<N; i++) {
- InputMethodInfo imi = mMethodList.get(i);
- Slog.i(TAG, "Adding: " + imi.getId());
- if (i > 0) sb.append(':');
- sb.append(imi.getId());
+ for (InputMethodInfo imi: mMethodList) {
if (defIm == null && imi.getIsDefaultResourceId() != 0) {
try {
- Resources res = mContext.createPackageContext(
+ Resources res = context.createPackageContext(
imi.getPackageName(), 0).getResources();
if (res.getBoolean(imi.getIsDefaultResourceId())) {
defIm = imi;
@@ -514,12 +501,10 @@
}
}
}
- if (defIm == null && N > 0) {
+ if (defIm == null && mMethodList.size() > 0) {
defIm = mMethodList.get(0);
Slog.i(TAG, "No default found, using " + defIm.getId());
}
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.ENABLED_INPUT_METHODS, sb.toString());
if (defIm != null) {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD, defIm.getId());
@@ -567,31 +552,10 @@
public List<InputMethodInfo> getEnabledInputMethodList() {
synchronized (mMethodMap) {
- return getEnabledInputMethodListLocked();
+ return mSettings.getEnabledInputMethodListLocked();
}
}
- List<InputMethodInfo> getEnabledInputMethodListLocked() {
- final ArrayList<InputMethodInfo> res = new ArrayList<InputMethodInfo>();
-
- final String enabledStr = Settings.Secure.getString(
- mContext.getContentResolver(),
- Settings.Secure.ENABLED_INPUT_METHODS);
- if (enabledStr != null) {
- final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
- splitter.setString(enabledStr);
-
- while (splitter.hasNext()) {
- InputMethodInfo info = mMethodMap.get(splitter.next());
- if (info != null) {
- res.add(info);
- }
- }
- }
-
- return res;
- }
-
public void addClient(IInputMethodClient client,
IInputContext inputContext, int uid, int pid) {
synchronized (mMethodMap) {
@@ -1471,7 +1435,7 @@
}
private boolean chooseNewDefaultIMELocked() {
- List<InputMethodInfo> enabled = getEnabledInputMethodListLocked();
+ List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
if (enabled != null && enabled.size() > 0) {
// We'd prefer to fall back on a system IME, since that is safer.
int i=enabled.size();
@@ -1650,7 +1614,7 @@
hideInputMethodMenu();
}
};
-
+
TypedArray a = context.obtainStyledAttributes(null,
com.android.internal.R.styleable.DialogPreference,
com.android.internal.R.attr.alertDialogStyle, 0);
@@ -1664,7 +1628,7 @@
.setIcon(a.getDrawable(
com.android.internal.R.styleable.DialogPreference_dialogTitle));
a.recycle();
-
+
mDialogBuilder.setSingleChoiceItems(mItems, checkedItem,
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
@@ -1738,81 +1702,45 @@
// Make sure this is a valid input method.
InputMethodInfo imm = mMethodMap.get(id);
if (imm == null) {
- if (imm == null) {
- throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
- }
+ throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
}
- StringBuilder builder = new StringBuilder(256);
+ List<Pair<String, ArrayList<String>>> enabledInputMethodsList = mSettings
+ .getEnabledInputMethodsAndSubtypeListLocked();
- boolean removed = false;
- String firstId = null;
-
- // Look through the currently enabled input methods.
- String enabledStr = Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.ENABLED_INPUT_METHODS);
- if (enabledStr != null) {
- final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
- splitter.setString(enabledStr);
- while (splitter.hasNext()) {
- String curId = splitter.next();
- if (curId.equals(id)) {
- if (enabled) {
- // We are enabling this input method, but it is
- // already enabled. Nothing to do. The previous
- // state was enabled.
- return true;
- }
- // We are disabling this input method, and it is
- // currently enabled. Skip it to remove from the
- // new list.
- removed = true;
- } else if (!enabled) {
- // We are building a new list of input methods that
- // doesn't contain the given one.
- if (firstId == null) firstId = curId;
- if (builder.length() > 0) builder.append(':');
- builder.append(curId);
+ if (enabled) {
+ for (Pair<String, ArrayList<String>> pair: enabledInputMethodsList) {
+ if (pair.first.equals(id)) {
+ // We are enabling this input method, but it is already enabled.
+ // Nothing to do. The previous state was enabled.
+ return true;
}
}
- }
-
- if (!enabled) {
- if (!removed) {
- // We are disabling the input method but it is already
- // disabled. Nothing to do. The previous state was
- // disabled.
+ mSettings.appendAndPutEnabledInputMethodLocked(id, false);
+ // Previous state was disabled.
+ return false;
+ } else {
+ StringBuilder builder = new StringBuilder();
+ if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
+ builder, enabledInputMethodsList, id)) {
+ // Disabled input method is currently selected, switch to another one.
+ String selId = Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.DEFAULT_INPUT_METHOD);
+ if (id.equals(selId)) {
+ Settings.Secure.putString(
+ mContext.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD,
+ enabledInputMethodsList.size() > 0
+ ? enabledInputMethodsList.get(0).first : "");
+ resetSelectedInputMethodSubtype();
+ }
+ // Previous state was enabled.
+ return true;
+ } else {
+ // We are disabling the input method but it is already disabled.
+ // Nothing to do. The previous state was disabled.
return false;
}
- // Update the setting with the new list of input methods.
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.ENABLED_INPUT_METHODS, builder.toString());
- // We the disabled input method is currently selected, switch
- // to another one.
- String selId = Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD);
- if (id.equals(selId)) {
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD,
- firstId != null ? firstId : "");
- resetSelectedInputMethodSubtype();
- }
- // Previous state was enabled.
- return true;
}
-
- // Add in the newly enabled input method.
- if (enabledStr == null || enabledStr.length() == 0) {
- enabledStr = id;
- } else {
- enabledStr = enabledStr + ':' + id;
- }
-
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.ENABLED_INPUT_METHODS, enabledStr);
-
- // Previous state was disabled.
- return false;
}
private void resetSelectedInputMethodSubtype() {
@@ -1862,6 +1790,161 @@
return mCurrentSubtype;
}
+ /**
+ * Utility class for putting and getting settings for InputMethod
+ * TODO: Move all putters and getters of settings to this class.
+ */
+ private static class InputMethodSettings {
+ // The string for enabled input method is saved as follows:
+ // example: ("ime0;subtype0;subtype1;subtype2:ime1:ime2;subtype0")
+ private static final char INPUT_METHOD_SEPARATER = ':';
+ private static final char INPUT_METHOD_SUBTYPE_SEPARATER = ';';
+ private final TextUtils.SimpleStringSplitter mStringColonSplitter =
+ new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATER);
+
+ private final TextUtils.SimpleStringSplitter mStringSemiColonSplitter =
+ new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER);
+
+ private final ContentResolver mResolver;
+ private final HashMap<String, InputMethodInfo> mMethodMap;
+ private final ArrayList<InputMethodInfo> mMethodList;
+
+ private String mEnabledInputMethodsStrCache;
+
+ private static void buildEnabledInputMethodsSettingString(
+ StringBuilder builder, Pair<String, ArrayList<String>> pair) {
+ String id = pair.first;
+ ArrayList<String> subtypes = pair.second;
+ builder.append(id);
+ if (subtypes.size() > 0) {
+ builder.append(subtypes.get(0));
+ for (int i = 1; i < subtypes.size(); ++i) {
+ builder.append(INPUT_METHOD_SUBTYPE_SEPARATER).append(subtypes.get(i));
+ }
+ }
+ }
+
+ public InputMethodSettings(
+ ContentResolver resolver, HashMap<String, InputMethodInfo> methodMap,
+ ArrayList<InputMethodInfo> methodList) {
+ mResolver = resolver;
+ mMethodMap = methodMap;
+ mMethodList = methodList;
+ }
+
+ public List<InputMethodInfo> getEnabledInputMethodListLocked() {
+ return createEnabledInputMethodListLocked(
+ getEnabledInputMethodsAndSubtypeListLocked());
+ }
+
+ // At the initial boot, the settings for input methods are not set,
+ // so we need to enable IME in that case.
+ public void enableAllIMEsIfThereIsNoEnabledIME() {
+ if (TextUtils.isEmpty(getEnabledInputMethodsStr())) {
+ StringBuilder sb = new StringBuilder();
+ final int N = mMethodList.size();
+ for (int i = 0; i < N; i++) {
+ InputMethodInfo imi = mMethodList.get(i);
+ Slog.i(TAG, "Adding: " + imi.getId());
+ if (i > 0) sb.append(':');
+ sb.append(imi.getId());
+ }
+ putEnabledInputMethodsStr(sb.toString());
+ }
+ }
+
+ public List<Pair<String, ArrayList<String>>> getEnabledInputMethodsAndSubtypeListLocked() {
+ ArrayList<Pair<String, ArrayList<String>>> imsList
+ = new ArrayList<Pair<String, ArrayList<String>>>();
+ final String enabledInputMethodsStr = getEnabledInputMethodsStr();
+ if (TextUtils.isEmpty(enabledInputMethodsStr)) {
+ return imsList;
+ }
+ mStringColonSplitter.setString(enabledInputMethodsStr);
+ while (mStringColonSplitter.hasNext()) {
+ String nextImsStr = mStringColonSplitter.next();
+ mStringSemiColonSplitter.setString(nextImsStr);
+ if (mStringSemiColonSplitter.hasNext()) {
+ ArrayList<String> subtypeHashes = new ArrayList<String>();
+ // The first element is ime id.
+ String imeId = mStringSemiColonSplitter.next();
+ while (mStringSemiColonSplitter.hasNext()) {
+ subtypeHashes.add(mStringSemiColonSplitter.next());
+ }
+ imsList.add(new Pair<String, ArrayList<String>>(imeId, subtypeHashes));
+ }
+ }
+ return imsList;
+ }
+
+ public void appendAndPutEnabledInputMethodLocked(String id, boolean reloadInputMethodStr) {
+ if (reloadInputMethodStr) {
+ getEnabledInputMethodsStr();
+ }
+ if (TextUtils.isEmpty(mEnabledInputMethodsStrCache)) {
+ // Add in the newly enabled input method.
+ putEnabledInputMethodsStr(id);
+ } else {
+ putEnabledInputMethodsStr(
+ mEnabledInputMethodsStrCache + INPUT_METHOD_SEPARATER + id);
+ }
+ }
+
+ /**
+ * Build and put a string of EnabledInputMethods with removing specified Id.
+ * @return the specified id was removed or not.
+ */
+ public boolean buildAndPutEnabledInputMethodsStrRemovingIdLocked(
+ StringBuilder builder, List<Pair<String, ArrayList<String>>> imsList, String id) {
+ boolean isRemoved = false;
+ boolean needsAppendSeparator = false;
+ for (Pair<String, ArrayList<String>> ims: imsList) {
+ String curId = ims.first;
+ if (curId.equals(id)) {
+ // We are disabling this input method, and it is
+ // currently enabled. Skip it to remove from the
+ // new list.
+ isRemoved = true;
+ } else {
+ if (needsAppendSeparator) {
+ builder.append(INPUT_METHOD_SEPARATER);
+ } else {
+ needsAppendSeparator = true;
+ }
+ buildEnabledInputMethodsSettingString(builder, ims);
+ }
+ }
+ if (isRemoved) {
+ // Update the setting with the new list of input methods.
+ putEnabledInputMethodsStr(builder.toString());
+ }
+ return isRemoved;
+ }
+
+ private List<InputMethodInfo> createEnabledInputMethodListLocked(
+ List<Pair<String, ArrayList<String>>> imsList) {
+ final ArrayList<InputMethodInfo> res = new ArrayList<InputMethodInfo>();
+ for (Pair<String, ArrayList<String>> ims: imsList) {
+ InputMethodInfo info = mMethodMap.get(ims.first);
+ if (info != null) {
+ res.add(info);
+ }
+ }
+ return res;
+ }
+
+ private void putEnabledInputMethodsStr(String str) {
+ Settings.Secure.putString(mResolver, Settings.Secure.ENABLED_INPUT_METHODS, str);
+ mEnabledInputMethodsStrCache = str;
+ }
+
+ private String getEnabledInputMethodsStr() {
+ mEnabledInputMethodsStrCache = Settings.Secure.getString(
+ mResolver, Settings.Secure.ENABLED_INPUT_METHODS);
+ return mEnabledInputMethodsStrCache;
+ }
+ }
+
// ----------------------------------------------------------------------
@Override
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 19f56a8..540c7fe 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -881,7 +881,6 @@
* the already-set timer.
*/
int pluggedType = intent.getIntExtra("plugged", 0);
- Slog.d(TAG, "ACTION_BATTERY_CHANGED pluggedType: " + pluggedType);
if (mScreenOff && shouldWifiStayAwake(stayAwakeConditions, mPluggedType) &&
!shouldWifiStayAwake(stayAwakeConditions, pluggedType)) {
long triggerTime = System.currentTimeMillis() + idleMillis;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 0727a79..30aed69 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -569,8 +569,10 @@
DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED, 0, 0,
mDataDescription, null);
- for (WindowState ws : mWindows) {
- sendDragStartedLw(ws, evt);
+ final int N = mWindows.size();
+ for (int i = 0; i < N; i++) {
+ // sendDragStartedLw() clones evt for local-process dispatch
+ sendDragStartedLw(mWindows.get(i), evt);
}
evt.recycle();
}
@@ -579,10 +581,17 @@
* designated window is potentially a drop recipient. There are race situations
* around DRAG_ENDED broadcast, so we make sure that once we've declared that
* the drag has ended, we never send out another DRAG_STARTED for this drag action.
+ *
+ * This method clones the 'event' parameter if it's being delivered to the same
+ * process, so it's safe for the caller to call recycle() on the event afterwards.
*/
- private void sendDragStartedLw(WindowState newWin, final DragEvent event) {
+ private void sendDragStartedLw(WindowState newWin, DragEvent event) {
if (!mDragEnded && newWin.isPotentialDragTarget()) {
try {
+ // clone for local callees since dispatch will recycle the event
+ if (Process.myPid() == newWin.mSession.mPid) {
+ event = DragEvent.obtain(event);
+ }
newWin.mClient.dispatchDragEvent(event);
// track each window that we've notified that the drag is starting
mNotifiedWindows.add(newWin);
@@ -608,6 +617,7 @@
}
DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED, 0, 0,
mDataDescription, null);
+ // sendDragStartedLw() clones 'event' if the window is process-local
sendDragStartedLw(newWin, event);
event.recycle();
}
@@ -632,6 +642,14 @@
}
void notifyMoveLw(float x, float y) {
+ final int myPid = Process.myPid();
+
+ // Move the surface to the given touch
+ mSurface.openTransaction();
+ mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY));
+ mSurface.closeTransaction();
+
+ // Tell the affected window
WindowState touchedWin = getTouchedWinAtPointLw(x, y);
try {
// have we dragged over a new window?
@@ -643,7 +661,9 @@
DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_EXITED,
0, 0, null, null);
mTargetWindow.mClient.dispatchDragEvent(evt);
- evt.recycle();
+ if (myPid != mTargetWindow.mSession.mPid) {
+ evt.recycle();
+ }
}
if (touchedWin != null) {
if (DEBUG_DRAG) {
@@ -652,7 +672,9 @@
DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION,
x, y, null, null);
touchedWin.mClient.dispatchDragEvent(evt);
- evt.recycle();
+ if (myPid != touchedWin.mSession.mPid) {
+ evt.recycle();
+ }
}
} catch (RemoteException e) {
Slog.w(TAG, "can't send drag notification to windows");
@@ -667,13 +689,16 @@
if (DEBUG_DRAG) {
Slog.d(TAG, "sending DROP to " + touchedWin);
}
+ final int myPid = Process.myPid();
DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP, x, y, null, mData);
try {
touchedWin.mClient.dispatchDragEvent(evt);
} catch (RemoteException e) {
Slog.w(TAG, "can't send drop notification to win " + touchedWin);
}
- evt.recycle();
+ if (myPid != touchedWin.mSession.mPid) {
+ evt.recycle();
+ }
}
}
@@ -749,13 +774,7 @@
case MotionEvent.ACTION_MOVE: {
synchronized (mWindowMap) {
- // move the surface to the latest touch point
- mDragState.mSurface.openTransaction();
- mDragState.mSurface.setPosition((int)(newX - mDragState.mThumbOffsetX),
- (int)(newY - mDragState.mThumbOffsetY));
- mDragState.mSurface.closeTransaction();
-
- // tell the involved window(s) where we are
+ // move the surface and tell the involved window(s) where we are
mDragState.notifyMoveLw(newX, newY);
}
} break;
@@ -3368,11 +3387,8 @@
}
// If this application has requested an explicit orientation,
// then use it.
- if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
- or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
- or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
- or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
- or == ActivityInfo.SCREEN_ORIENTATION_USER) {
+ if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+ && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
return or;
}
findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
@@ -5403,7 +5419,6 @@
mDragState.reset();
mDragState = null;
}
-
}
}
} finally {
@@ -5535,7 +5550,7 @@
inputWindow.frameTop = 0;
inputWindow.frameRight = mDisplay.getWidth();
inputWindow.frameBottom = mDisplay.getHeight();
-
+
inputWindow.visibleFrameLeft = inputWindow.frameLeft;
inputWindow.visibleFrameTop = inputWindow.frameTop;
inputWindow.visibleFrameRight = inputWindow.frameRight;
@@ -6195,9 +6210,8 @@
mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder());
- // !!! TODO: call into the input monitor to sever the current touch event flow
- // and redirect to the drag "window"; also extract the current touch (x, y)
- // in screen coordinates
+ // !!! TODO: extract the current touch (x, y) in screen coordinates. That
+ // will let us eliminate the (touchX,touchY) parameters from the API.
mDragState.register();
mInputMonitor.updateInputWindowsLw();
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
index 4430533..0dc836d 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
@@ -101,6 +101,8 @@
mSmallPaint.setAntiAlias(false);
canvas.drawLine(0.0f, 0.0f, 400.0f, 0.0f, mSmallPaint);
mSmallPaint.setAntiAlias(true);
+ canvas.drawLine(0.0f, 0.0f, 0.0f, 400.0f, mSmallPaint);
+ canvas.drawLine(0.0f, 400.0f, 400.0f, 400.0f, mSmallPaint);
canvas.translate(120.0f, 0.0f);
mAlphaPaint.setShader(mShader);
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 2d7ee13..e30cf4a 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -727,7 +727,7 @@
}
},
- new Test("Persistent with numbers 222") {
+ new Test("Persistent with numbers 22") {
public void run() {
mNM.notify(1, notificationWithNumbers(22));
}