Merge "Implement allocation resizing."
diff --git a/api/current.xml b/api/current.xml
index c769794..07724ab 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -6268,17 +6268,6 @@
visibility="public"
>
</field>
-<field name="kraken_resource_pad56"
- type="int"
- transient="false"
- volatile="false"
- value="16843465"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="kraken_resource_pad6"
type="int"
transient="false"
@@ -7687,6 +7676,17 @@
visibility="public"
>
</field>
+<field name="popupAnimationStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843465"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="popupBackground"
type="int"
transient="false"
@@ -21025,6 +21025,21 @@
visibility="public"
>
</constructor>
+<method name="addChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.ViewGroup">
+</parameter>
+<parameter name="child" type="android.view.View">
+</parameter>
+</method>
<method name="addTransitionListener"
return="void"
abstract="false"
@@ -21038,36 +21053,6 @@
<parameter name="listener" type="android.animation.LayoutTransition.TransitionListener">
</parameter>
</method>
-<method name="childAdd"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="parent" type="android.view.ViewGroup">
-</parameter>
-<parameter name="child" type="android.view.View">
-</parameter>
-</method>
-<method name="childRemove"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="parent" type="android.view.ViewGroup">
-</parameter>
-<parameter name="child" type="android.view.View">
-</parameter>
-</method>
<method name="getAnimator"
return="android.animation.Animator"
abstract="false"
@@ -21144,6 +21129,36 @@
visibility="public"
>
</method>
+<method name="hideChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.ViewGroup">
+</parameter>
+<parameter name="child" type="android.view.View">
+</parameter>
+</method>
+<method name="removeChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.ViewGroup">
+</parameter>
+<parameter name="child" type="android.view.View">
+</parameter>
+</method>
<method name="removeTransitionListener"
return="void"
abstract="false"
@@ -21245,6 +21260,21 @@
<parameter name="delay" type="long">
</parameter>
</method>
+<method name="showChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.ViewGroup">
+</parameter>
+<parameter name="child" type="android.view.View">
+</parameter>
+</method>
<field name="APPEARING"
type="int"
transient="false"
@@ -55046,6 +55076,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"
@@ -55079,6 +55120,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"
@@ -55090,6 +55153,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"
@@ -134925,6 +135010,17 @@
visibility="public"
>
</method>
+<method name="isExternalStorageRemovable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<field name="DIRECTORY_ALARMS"
type="java.lang.String"
transient="false"
@@ -189868,6 +189964,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"
@@ -189879,15 +189985,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"
@@ -203374,6 +203472,53 @@
>
</field>
</class>
+<class name="View.DragThumbnailBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ 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"
@@ -223693,7 +223838,7 @@
>
</method>
<method name="getInAnimation"
- return="android.view.animation.Animation"
+ return="android.animation.ObjectAnimator<?>"
abstract="false"
native="false"
synchronized="false"
@@ -223704,7 +223849,7 @@
>
</method>
<method name="getOutAnimation"
- return="android.view.animation.Animation"
+ return="android.animation.ObjectAnimator<?>"
abstract="false"
native="false"
synchronized="false"
@@ -223820,7 +223965,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"
@@ -223848,7 +223993,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/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index 69ad67e..52f0f16 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -459,21 +459,22 @@
* @param transitionType one of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING},
* {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose
* duration is being set.
- * @param animator The animation being assigned.
+ * @param animator The animation being assigned. A value of <code>null</code> means that no
+ * animation will be run for the specified transitionType.
*/
public void setAnimator(int transitionType, Animator animator) {
switch (transitionType) {
case CHANGE_APPEARING:
- mChangingAppearingAnim = (animator != null) ? animator : defaultChangeIn;
+ mChangingAppearingAnim = animator;
break;
case CHANGE_DISAPPEARING:
- mChangingDisappearingAnim = (animator != null) ? animator : defaultChangeOut;
+ mChangingDisappearingAnim = animator;
break;
case APPEARING:
- mAppearingAnim = (animator != null) ? animator : defaultFadeIn;
+ mAppearingAnim = animator;
break;
case DISAPPEARING:
- mDisappearingAnim = (animator != null) ? animator : defaultFadeOut;
+ mDisappearingAnim = animator;
break;
}
}
@@ -516,6 +517,14 @@
* transition is occuring because an item is being added to or removed from the parent.
*/
private void runChangeTransition(final ViewGroup parent, View newView, final int changeReason) {
+
+ Animator baseAnimator = (changeReason == APPEARING) ?
+ mChangingAppearingAnim : mChangingDisappearingAnim;
+ // If the animation is null, there's nothing to do
+ if (baseAnimator == null) {
+ return;
+ }
+
// reset the inter-animation delay, in case we use it later
staggerDelay = 0;
@@ -540,9 +549,10 @@
}
// Make a copy of the appropriate animation
- final Animator anim = (changeReason == APPEARING) ?
- mChangingAppearingAnim.clone() :
- mChangingDisappearingAnim.clone();
+ final Animator anim = baseAnimator.clone();
+
+ // Cache the animation in case we need to cancel it later
+ currentAnimations.put(child, anim);
// Set the target object for the animation
anim.setTarget(child);
@@ -553,13 +563,10 @@
// Add a listener to track layout changes on this view. If we don't get a callback,
// then there's nothing to animate.
- View.OnLayoutChangeListener listener = new View.OnLayoutChangeListener() {
+ final View.OnLayoutChangeListener listener = new View.OnLayoutChangeListener() {
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
- // Cache the animation in case we need to cancel it later
- currentAnimations.put(child, anim);
-
// Tell the animation to extract end values from the changed object
anim.setupEndValues();
@@ -577,19 +584,6 @@
anim.setStartDelay(startDelay);
anim.setDuration(duration);
- // Remove the animation from the cache when it ends
- anim.addListener(new AnimatorListenerAdapter() {
- private boolean canceled = false;
- public void onAnimationCancel(Animator animator) {
- // we remove canceled animations immediately, not here
- canceled = true;
- }
- public void onAnimationEnd(Animator animator) {
- if (!canceled) {
- currentAnimations.remove(child);
- }
- }
- });
if (anim instanceof ObjectAnimator) {
((ObjectAnimator) anim).setCurrentPlayTime(0);
}
@@ -601,6 +595,22 @@
layoutChangeListenerMap.remove(child);
}
};
+ // Remove the animation from the cache when it ends
+ anim.addListener(new AnimatorListenerAdapter() {
+ private boolean canceled = false;
+ public void onAnimationCancel(Animator animator) {
+ // we remove canceled animations immediately, not here
+ canceled = true;
+ child.removeOnLayoutChangeListener(listener);
+ layoutChangeListenerMap.remove(child);
+ }
+ public void onAnimationEnd(Animator animator) {
+ if (!canceled) {
+ currentAnimations.remove(child);
+ }
+ }
+ });
+
child.addOnLayoutChangeListener(listener);
// cache the listener for later removal
layoutChangeListenerMap.put(child, listener);
@@ -630,6 +640,14 @@
* @param child The View being added to the ViewGroup.
*/
private void runAppearingTransition(final ViewGroup parent, final View child) {
+ if (mAppearingAnim == null) {
+ if (mListeners != null) {
+ for (TransitionListener listener : mListeners) {
+ listener.endTransition(LayoutTransition.this, parent, child, APPEARING);
+ }
+ }
+ return;
+ }
Animator anim = mAppearingAnim.clone();
anim.setTarget(child);
anim.setStartDelay(mAppearingDelay);
@@ -656,13 +674,22 @@
* @param child The View being removed from the ViewGroup.
*/
private void runDisappearingTransition(final ViewGroup parent, final View child) {
+ if (mDisappearingAnim == null) {
+ if (mListeners != null) {
+ for (TransitionListener listener : mListeners) {
+ listener.endTransition(LayoutTransition.this, parent, child, DISAPPEARING);
+ }
+ }
+ return;
+ }
Animator anim = mDisappearingAnim.clone();
anim.setStartDelay(mDisappearingDelay);
anim.setDuration(mDisappearingDuration);
anim.setTarget(child);
if (mListeners != null) {
anim.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd() {
+ @Override
+ public void onAnimationEnd(Animator anim) {
for (TransitionListener listener : mListeners) {
listener.endTransition(LayoutTransition.this, parent, child, DISAPPEARING);
}
@@ -684,7 +711,7 @@
* @param parent The ViewGroup to which the View is being added.
* @param child The View being added to the ViewGroup.
*/
- public void childAdd(ViewGroup parent, View child) {
+ public void addChild(ViewGroup parent, View child) {
if (mListeners != null) {
for (TransitionListener listener : mListeners) {
listener.startTransition(this, parent, child, APPEARING);
@@ -695,6 +722,19 @@
}
/**
+ * This method is called by ViewGroup when a child view is about to be added to the
+ * container. This callback starts the process of a transition; we grab the starting
+ * values, listen for changes to all of the children of the container, and start appropriate
+ * animations.
+ *
+ * @param parent The ViewGroup to which the View is being added.
+ * @param child The View being added to the ViewGroup.
+ */
+ public void showChild(ViewGroup parent, View child) {
+ addChild(parent, child);
+ }
+
+ /**
* This method is called by ViewGroup when a child view is about to be removed from the
* container. This callback starts the process of a transition; we grab the starting
* values, listen for changes to all of the children of the container, and start appropriate
@@ -703,7 +743,7 @@
* @param parent The ViewGroup from which the View is being removed.
* @param child The View being removed from the ViewGroup.
*/
- public void childRemove(ViewGroup parent, View child) {
+ public void removeChild(ViewGroup parent, View child) {
if (mListeners != null) {
for (TransitionListener listener : mListeners) {
listener.startTransition(this, parent, child, DISAPPEARING);
@@ -714,6 +754,19 @@
}
/**
+ * This method is called by ViewGroup when a child view is about to be removed from the
+ * container. This callback starts the process of a transition; we grab the starting
+ * values, listen for changes to all of the children of the container, and start appropriate
+ * animations.
+ *
+ * @param parent The ViewGroup from which the View is being removed.
+ * @param child The View being removed from the ViewGroup.
+ */
+ public void hideChild(ViewGroup parent, View child) {
+ removeChild(parent, child);
+ }
+
+ /**
* Add a listener that will be called when the bounds of the view change due to
* layout processing.
*
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/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index f0d0fb4..a98a305 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -410,8 +410,16 @@
* @see #unlock()
*/
/* package */ void lock() {
+ lock(false);
+ }
+ private void lock(boolean forced) {
+ // make sure this method is NOT being called from a 'synchronized' method
+ if (Thread.holdsLock(this)) {
+ // STOPSHIP change the following line to Log.w()
+ throw new IllegalStateException("don't lock() while in a synchronized method");
+ }
verifyDbIsOpen();
- if (!mLockingEnabled) return;
+ if (!forced && !mLockingEnabled) return;
mLock.lock();
if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
if (mLock.getHoldCount() == 1) {
@@ -421,7 +429,6 @@
}
}
}
-
/**
* Locks the database for exclusive access. The database lock must be held when
* touch the native sqlite3* object since it is single threaded and uses
@@ -431,15 +438,7 @@
* @see #unlockForced()
*/
private void lockForced() {
- verifyDbIsOpen();
- mLock.lock();
- if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
- if (mLock.getHoldCount() == 1) {
- // Use elapsed real-time since the CPU may sleep when waiting for IO
- mLockAcquiredWallTime = SystemClock.elapsedRealtime();
- mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
- }
- }
+ lock(true);
}
/**
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index c7cbed6..e8ae7e6 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -18,6 +18,7 @@
import java.io.File;
+import android.content.res.Resources;
import android.os.storage.IMountService;
/**
@@ -116,6 +117,19 @@
* happened. You can determine its current state with
* {@link #getExternalStorageState()}.
*
+ * <p><em>Note: don't be confused by the word "external" here. This
+ * directory can better be thought as media/shared storage. It is a
+ * filesystem that can hold a relatively large amount of data and that
+ * is shared across all applications (does not enforce permissions).
+ * Traditionally this is an SD card, but it may also be implemented as
+ * built-in storage in a device that is distinct from the protected
+ * internal storage and can be mounted as a filesystem on a computer.</em></p>
+ *
+ * <p>In devices with multiple "external" storage directories (such as
+ * both secure app storage and mountable shared storage), this directory
+ * represents the "primary" external storage that the user will interact
+ * with.</p>
+ *
* <p>Applications should not directly use this top-level directory, in
* order to avoid polluting the user's root namespace. Any files that are
* private to the application should be placed in a directory returned
@@ -130,6 +144,9 @@
*
* {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
* monitor_storage}
+ *
+ * @see #getExternalStorageState()
+ * @see #isExternalStorageRemovable()
*/
public static File getExternalStorageDirectory() {
return EXTERNAL_STORAGE_DIRECTORY;
@@ -359,11 +376,9 @@
public static final String MEDIA_UNMOUNTABLE = "unmountable";
/**
- * Gets the current state of the external storage device.
- * Note: This call should be deprecated as it doesn't support
- * multiple volumes.
+ * Gets the current state of the primary "external" storage device.
*
- * <p>See {@link #getExternalStorageDirectory()} for an example of its use.
+ * <p>See {@link #getExternalStorageDirectory()} for more information.
*/
public static String getExternalStorageState() {
try {
@@ -377,6 +392,19 @@
}
}
+ /**
+ * Returns whether the primary "external" storage device is removable.
+ * If true is returned, this device is for example an SD card that the
+ * user can remove. If false is returned, the storage is built into
+ * the device and can not be physically removed.
+ *
+ * <p>See {@link #getExternalStorageDirectory()} for more information.
+ */
+ public static boolean isExternalStorageRemovable() {
+ return Resources.getSystem().getBoolean(
+ com.android.internal.R.bool.config_externalStorageRemovable);
+ }
+
static File getDirectory(String variableName, String defaultPath) {
String path = System.getenv(variableName);
return path == null ? new File(defaultPath) : new File(path);
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 4c01f4f..63450de 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -615,7 +615,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 +3956,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 +3975,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);
@@ -4905,6 +4907,9 @@
}
if ((changed & VISIBILITY_MASK) != 0) {
+ if (mParent instanceof ViewGroup) {
+ ((ViewGroup)mParent).onChildVisibilityChanged(this, (flags & VISIBILITY_MASK));
+ }
dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
}
@@ -5147,7 +5152,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
@@ -6202,7 +6207,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;
@@ -6233,7 +6239,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;
@@ -6272,7 +6279,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;
@@ -7422,8 +7430,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) {
@@ -9830,40 +9837,99 @@
}
/**
+ * !!! 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 class DragThumbnailBuilder {
+ private View mView;
+
+ /**
+ * Construct a thumbnail builder object for use with the given view.
+ * @param view
+ */
+ public DragThumbnailBuilder(View view) {
+ mView = 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) {
+ thumbnailSize.set(mView.getWidth(), mView.getHeight());
+ thumbnailTouchPoint.set(thumbnailSize.x / 2, thumbnailSize.y / 2);
+ }
+
+ /**
+ * 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) {
+ mView.draw(canvas);
+ }
+ }
+
+ /**
* 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);
@@ -9885,7 +9951,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 8a3db38..e71a4d6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -36,7 +36,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 +71,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
@@ -323,6 +321,10 @@
// being animated.
private ArrayList<View> mTransitioningViews;
+ // List of children changing visibility. This is used to potentially keep rendering
+ // views during a transition when they otherwise would have become gone/invisible
+ private ArrayList<View> mVisibilityChangingChildren;
+
public ViewGroup(Context context) {
super(context);
initViewGroup();
@@ -758,6 +760,32 @@
}
/**
+ * @hide
+ * @param child
+ * @param visibility
+ */
+ void onChildVisibilityChanged(View child, int visibility) {
+ if (mTransition != null) {
+ if (visibility == VISIBLE) {
+ mTransition.showChild(this, child);
+ } else {
+ mTransition.hideChild(this, child);
+ }
+ if (visibility != VISIBLE) {
+ // Only track this on disappearing views - appearing views are already visible
+ // and don't need special handling during drawChild()
+ if (mVisibilityChangingChildren == null) {
+ mVisibilityChangingChildren = new ArrayList<View>();
+ }
+ mVisibilityChangingChildren.add(child);
+ if (mTransitioningViews != null && mTransitioningViews.contains(child)) {
+ addDisappearingView(child);
+ }
+ }
+ }
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
@@ -838,9 +866,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) {
@@ -853,10 +879,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;
+ }
}
}
@@ -871,7 +900,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.
@@ -891,7 +923,7 @@
root.setDragFocus(event, target);
mCurrentDragView = target;
}
-
+
// Dispatch the actual drag location notice, localized into its coordinates
if (target != null) {
event.mX = mLocalPoint.x;
@@ -905,7 +937,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;
@@ -927,8 +959,6 @@
// 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--) {
@@ -937,20 +967,7 @@
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;
}
}
@@ -1078,7 +1095,7 @@
continue;
}
- if (!isTransformedTouchPointInView(x, y, child)) {
+ if (!isTransformedTouchPointInView(x, y, child, null)) {
// New pointer is out of child's bounds.
continue;
}
@@ -1262,7 +1279,8 @@
/* 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) {
+ private final 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) {
@@ -1273,7 +1291,11 @@
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,
@@ -2598,7 +2620,7 @@
}
if (mTransition != null) {
- mTransition.childAdd(this, child);
+ mTransition.addChild(this, child);
}
if (!checkLayoutParams(params)) {
@@ -2817,7 +2839,7 @@
private void removeViewInternal(int index, View view) {
if (mTransition != null) {
- mTransition.childRemove(this, view);
+ mTransition.removeChild(this, view);
}
boolean clearChildFocus = false;
@@ -2893,7 +2915,7 @@
final View view = children[i];
if (mTransition != null) {
- mTransition.childRemove(this, view);
+ mTransition.removeChild(this, view);
}
if (view == focused) {
@@ -2962,7 +2984,7 @@
final View view = children[i];
if (mTransition != null) {
- mTransition.childRemove(this, view);
+ mTransition.removeChild(this, view);
}
if (view == focused) {
@@ -3005,7 +3027,7 @@
*/
protected void removeDetachedView(View child, boolean animate) {
if (mTransition != null) {
- mTransition.childRemove(this, child);
+ mTransition.removeChild(this, child);
}
if (child == mFocused) {
@@ -4025,11 +4047,16 @@
final ArrayList<View> disappearingChildren = mDisappearingChildren;
if (disappearingChildren != null && disappearingChildren.contains(view)) {
disappearingChildren.remove(view);
- if (view.mAttachInfo != null) {
- view.dispatchDetachedFromWindow();
- }
- if (view.mParent != null) {
- view.mParent = null;
+ if (mVisibilityChangingChildren != null &&
+ mVisibilityChangingChildren.contains(view)) {
+ mVisibilityChangingChildren.remove(view);
+ } else {
+ if (view.mAttachInfo != null) {
+ view.dispatchDetachedFromWindow();
+ }
+ if (view.mParent != null) {
+ view.mParent = null;
+ }
}
mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
}
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/Adapter.java b/core/java/android/widget/Adapter.java
index f2b3e2a..9b6c5a4 100644
--- a/core/java/android/widget/Adapter.java
+++ b/core/java/android/widget/Adapter.java
@@ -72,7 +72,7 @@
long getItemId(int position);
/**
- * Indicated whether the item ids are stable across changes to the
+ * Indicates whether the item ids are stable across changes to the
* underlying data.
*
* @return True if the same id always refers to the same object.
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index ab75420..f5afb94 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -172,7 +172,7 @@
int mItemCount;
/**
- * The number of items in the adapter before a data changed event occured.
+ * The number of items in the adapter before a data changed event occurred.
*/
int mOldItemCount;
@@ -557,7 +557,7 @@
/**
* @return The number of items owned by the Adapter associated with this
* AdapterView. (This is the number of data items, which may be
- * larger than the number of visible view.)
+ * larger than the number of visible views.)
*/
@ViewDebug.CapturedViewProperty
public int getCount() {
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/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 6799ffd..d6c2db1 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -178,7 +178,10 @@
attrs, com.android.internal.R.styleable.PopupWindow, defStyleAttr, defStyleRes);
mBackground = a.getDrawable(R.styleable.PopupWindow_popupBackground);
- mAnimationStyle = a.getResourceId(R.styleable.PopupWindow_windowAnimationStyle, -1);
+
+ final int animStyle = a.getResourceId(R.styleable.PopupWindow_popupAnimationStyle, -1);
+ mAnimationStyle = animStyle == com.android.internal.R.style.Animation_PopupWindow ? -1 :
+ animStyle;
// If this is a StateListDrawable, try to find and store the drawable to be
// used when the drop-down is placed above its anchor view, and the one to be
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0c50742..70c6378 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -64,7 +64,6 @@
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextWatcher;
-import android.text.method.ArrowKeyMovementMethod;
import android.text.method.DateKeyListener;
import android.text.method.DateTimeKeyListener;
import android.text.method.DialerKeyListener;
@@ -1160,7 +1159,7 @@
fixFocusableAndClickableSettings();
- // SelectionModifierCursorController depends on canSelectText, which depends on mMovement
+ // SelectionModifierCursorController depends on textCanBeSelected, which depends on mMovement
prepareCursorControllers();
}
@@ -2730,7 +2729,7 @@
sendAfterTextChanged((Editable) text);
}
- // SelectionModifierCursorController depends on canSelectText, which depends on text
+ // SelectionModifierCursorController depends on textCanBeSelected, which depends on text
prepareCursorControllers();
}
@@ -6667,6 +6666,8 @@
} else {
terminateSelectionActionMode();
}
+
+ mLastTouchOffset = -1;
}
startStopMarquee(focused);
@@ -6899,7 +6900,7 @@
mInsertionPointCursorController = null;
}
- if (canSelectText() && mLayout != null) {
+ if (textCanBeSelected() && mLayout != null) {
if (mSelectionModifierCursorController == null) {
mSelectionModifierCursorController = new SelectionModifierCursorController();
}
@@ -7119,7 +7120,7 @@
public boolean onKeyShortcut(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_A:
- if (canSelectAll()) {
+ if (canSelectText()) {
return onTextContextMenuItem(ID_SELECT_ALL);
}
@@ -7150,11 +7151,11 @@
return super.onKeyShortcut(keyCode, event);
}
- private boolean canSelectAll() {
- return canSelectText() && mText.length() != 0;
+ private boolean canSelectText() {
+ return textCanBeSelected() && mText.length() != 0;
}
- private boolean canSelectText() {
+ private boolean textCanBeSelected() {
// prepareCursorController() relies on this method.
// If you change this condition, make sure prepareCursorController is called anywhere
// the value of this condition might be changed.
@@ -7624,7 +7625,7 @@
boolean atLeastOne = false;
- if (canSelectAll()) {
+ if (canSelectText()) {
menu.add(0, ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
setIcon(com.android.internal.R.drawable.ic_menu_select_all).
setAlphabeticShortcut('a');
diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp
index 05e1ff3..1b68ba9 100644
--- a/core/jni/android_database_SQLiteDatabase.cpp
+++ b/core/jni/android_database_SQLiteDatabase.cpp
@@ -77,7 +77,7 @@
static void sqlLogger(void *databaseName, int iErrCode, const char *zMsg) {
// skip printing this message if it is due to certain types of errors
- if (iErrCode == SQLITE_CONSTRAINT) return;
+ if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT) return;
LOGI("sqlite returned: error code = %d, msg = %s\n", iErrCode, zMsg);
}
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index cb1556b1..7521af4 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -50,7 +50,20 @@
*/
#ifdef USE_OPENGL_RENDERER
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+// Debug
#define DEBUG_RENDERER 0
+#define PROFILE_RENDERER 0
+
+// Debug
+#if DEBUG_RENDERER
+ #define RENDERER_LOGD(...) LOGD(__VA_ARGS__)
+#else
+ #define RENDERER_LOGD(...)
+#endif
// ----------------------------------------------------------------------------
// Java APIs
@@ -66,7 +79,8 @@
// ----------------------------------------------------------------------------
static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject canvas) {
-#if DEBUG_RENDERER
+ RENDERER_LOGD("Create OpenGLRenderer");
+#if PROFILE_RENDERER
return new OpenGLDebugRenderer;
#else
return new OpenGLRenderer;
@@ -75,6 +89,7 @@
static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer) {
+ RENDERER_LOGD("Destroy OpenGLRenderer");
delete renderer;
}
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_gray.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_gray.9.png
index 53ed136..abb91cc 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_gray.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_green.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_green.9.png
index 6455790..7c4f40e 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_green.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_red.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_red.9.png
index 49bb9c1..6dbf925 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_red.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png
index b3c4c4c..b05a49f 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png
index 00dea6ec..109be42 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_pressed.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_pressed.9.png
index 45b1850..2800cab 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_pressed.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_gray.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_gray.9.png
index 35b3529..51cbfa6 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_gray.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_green.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_green.9.png
index 720de7f..ca51ccc 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_green.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_red.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_red.9.png
index b3387be..fd98571 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_red.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png
index 7ddfbcc..723815b 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png
index 1855e5f..030c9e9 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_pressed.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_pressed.9.png
index 844f304..ffc5433 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_pressed.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_pressed.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_pressed.9.png
index 0cfd09d..75c8162 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_pressed.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_small_pressed.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_small_pressed.9.png
index ee030fbe..aebfa29 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_small_pressed.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_small_unpressed.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_small_unpressed.9.png
index 7140957..ed416f1 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_small_unpressed.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_small_unpressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_unpressed.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_unpressed.9.png
index 1eeabf4..d063229 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_unpressed.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_unpressed.9.png
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/values/attrs.xml b/core/res/res/values/attrs.xml
index 5df95de..8e2b762 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2363,7 +2363,7 @@
</declare-styleable>
<declare-styleable name="PopupWindow">
<attr name="popupBackground" format="reference|color" />
- <attr name="windowAnimationStyle" />
+ <attr name="popupAnimationStyle" format="reference" />
</declare-styleable>
<declare-styleable name="ViewAnimator">
<!-- Identifier for the animation to use when a view is shown. -->
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/config.xml b/core/res/res/values/config.xml
index f704874..71967d4 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -82,6 +82,15 @@
<!-- Set to true if external storage is case sensitive.
Typically external storage is FAT, which is case insensitive. -->
<bool name="config_caseSensitiveExternalStorage">false</bool>
+
+ <!-- A product with no SD card == not removable. -->
+ <bool name="config_externalStorageRemovable" product="nosdcard">false</bool>
+ <!-- Configures whether the primary external storage device is
+ removable. For example, if external storage is on an SD card,
+ it is removable; if it is built in to the device, it is not removable.
+ The default product has external storage on an SD card, which is
+ removable. -->
+ <bool name="config_externalStorageRemovable" product="default">true</bool>
<!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION.
Please don't copy them, copy anything else. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 8592820..35f8df5 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1256,6 +1256,7 @@
<public type="attr" name="textSelectHandleRight" id="0x010102c6" />
<public type="attr" name="textSelectHandle" id="0x010102c7" />
<public type="attr" name="textSelectHandleWindowStyle" id="0x010102c8" />
+ <public type="attr" name="popupAnimationStyle" id="0x010102c9" />
<public-padding type="attr" name="kraken_resource_pad" end="0x01010300" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 6e9530c..3dfaf7f 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -196,6 +196,9 @@
<item name="windowExitAnimation">@anim/fade_out</item>
</style>
+ <!-- A special animation value used internally for popup windows. -->
+ <style name="Animation.PopupWindow" />
+
<!-- Status Bar Styles -->
<style name="TextAppearance.StatusBar">
@@ -564,6 +567,7 @@
<style name="Widget.PopupWindow">
<item name="android:popupBackground">@android:drawable/editbox_dropdown_background_dark</item>
+ <item name="android:popupAnimationStyle">@android:style/Animation.PopupWindow</item>
</style>
<!-- Default style for {@link android.app.FragmentBreadCrumbs} view. -->
@@ -587,7 +591,7 @@
</style>
<style name="Widget.QuickContactBadge">
- <item name="android:layout_width">50dip</item>
+ <item name="android:layout_width">47.33333dip</item>
<item name="android:layout_height">56dip</item>
<item name="android:background">@android:drawable/quickcontact_badge</item>
<item name="android:clickable">true</item>
@@ -883,7 +887,7 @@
<!-- Style for the small popup windows that contain text selection anchors. -->
<style name="Widget.TextSelectHandle">
- <item name="android:windowAnimationStyle">@android:style/Animation.TextSelectHandle</item>
+ <item name="android:popupAnimationStyle">@android:style/Animation.TextSelectHandle</item>
</style>
<!-- Style for animating text selection handles. -->
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..2c7633d 100644
--- a/docs/html/guide/practices/design/responsiveness.jd
+++ b/docs/html/guide/practices/design/responsiveness.jd
@@ -1,11 +1,37 @@
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>
</div>
+<p>It's possible to write code that wins every performance test in the world, but still sends users
+in a fiery rage when they try to use the application. These are the applications that aren't
+<em>responsive</em> enough — the ones that feel
+sluggish, hang or freeze for significant periods, or take too long to process
+input. </p>
+
+<p>In Android, the system guards against applications that are insufficiently responsive for a
+period of time by displaying a dialog to the user, called the Application Not Responding (ANR)
+dialog. The user can choose to let the application continue, but the user won't appreciate having to
+act on this dialog every time he or she uses your application. So it's important to design
+responsiveness into your application, so that the system never has cause to display an ANR to the
+user. </p>
+
<p>It's possible to write code that wins every performance test in the world,
but still sends users in a fiery rage when they try to use the application.
These are the applications that aren't <em>responsive</em> enough — the
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/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/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 9a19056..d283dea3 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -346,6 +346,15 @@
return b;
}
+ /**
+ * Creates a new bitmap, scaled from an existing bitmap.
+ *
+ * @param src The source bitmap.
+ * @param dstWidth The new bitmap's desired width.
+ * @param dstHeight The new bitmap's desired height.
+ * @param filter true if the source should be filtered.
+ * @return the new scaled bitmap.
+ */
public static Bitmap createScaledBitmap(Bitmap src, int dstWidth,
int dstHeight, boolean filter) {
Matrix m;
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index a4933c0..2952a66 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -65,8 +65,8 @@
PathCache pathCache;
PatchCache patchCache;
TextDropShadowCache dropShadowCache;
- GammaFontRenderer fontRenderer;
FboCache fboCache;
+ GammaFontRenderer fontRenderer;
Line line;
}; // class Caches
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 5485113..8389e56 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -437,8 +437,9 @@
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, mCacheWidth, mCacheHeight, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ mLinearFiltering = false;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 4fb8f8d..f10efad 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -156,8 +156,16 @@
DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
uint32_t len, int numGlyphs, uint32_t radius);
- GLuint getTexture() {
+ GLuint getTexture(bool linearFiltering = false) {
checkInit();
+ if (linearFiltering != mLinearFiltering) {
+ mLinearFiltering = linearFiltering;
+ const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
+
+ glBindTexture(GL_TEXTURE_2D, mTextureId);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
+ }
return mTextureId;
}
@@ -252,6 +260,8 @@
bool mInitialized;
+ bool mLinearFiltering;
+
void computeGaussianWeights(float* weights, int32_t radius);
void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
int32_t width, int32_t height);
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index c698b5a..219fd5e 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -53,6 +53,15 @@
mSimpleMatrix = true;
}
+#define EPSILON 0.00001f
+#define almost(u, v) (fabs((u) - (v)) < EPSILON)
+
+bool Matrix4::changesBounds() {
+ return !(almost(data[0], 1.0f) && almost(data[1], 0.0f) && almost(data[2], 0.0f) &&
+ almost(data[4], 0.0f) && almost(data[5], 1.0f) && almost(data[6], 0.0f) &&
+ almost(data[8], 0.0f) && almost(data[9], 0.0f) && almost(data[10], 1.0f));
+}
+
void Matrix4::load(const float* v) {
memcpy(data, v, sizeof(data));
mSimpleMatrix = false;
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 0608efe..fe81159 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -103,6 +103,8 @@
multiply(u);
}
+ bool changesBounds();
+
void copyTo(float* v) const;
void copyTo(SkMatrix& v) const;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 0810fb8..e3790f5 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -113,8 +113,6 @@
///////////////////////////////////////////////////////////////////////////////
OpenGLRenderer::OpenGLRenderer(): mCaches(Caches::getInstance()) {
- LOGD("Create OpenGLRenderer");
-
mShader = NULL;
mColorFilter = NULL;
mHasShadow = false;
@@ -133,7 +131,6 @@
}
OpenGLRenderer::~OpenGLRenderer() {
- LOGD("Destroy OpenGLRenderer");
// The context has already been destroyed at this point, do not call
// GL APIs. All GL state should be kept in Caches.h
}
@@ -767,8 +764,10 @@
GLuint textureUnit = 0;
glActiveTexture(gTextureUnits[textureUnit]);
- setupTextureAlpha8(fontRenderer.getTexture(), 0, 0, textureUnit, x, y, r, g, b, a,
- mode, false, true);
+ // Assume that the modelView matrix does not force scales, rotates, etc.
+ const bool linearFilter = mSnapshot->transform->changesBounds();
+ setupTextureAlpha8(fontRenderer.getTexture(linearFilter), 0, 0, textureUnit,
+ x, y, r, g, b, a, mode, false, true);
const Rect& clip = mSnapshot->getLocalClip();
clearLayerRegions();
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 062c986..c736a1c 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -141,6 +141,7 @@
}
if (clipped) {
+ clipRect->snapToPixelBoundaries();
flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip;
}
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/rsContext.cpp b/libs/rs/rsContext.cpp
index 6940033..493a092 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -258,14 +258,14 @@
sprintf(buffer, "Frame %i ms, Script %i ms", 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() - 5);
- 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() - 6);
mStateFont.setFontColor(oldR, oldG, oldB, oldA);
}
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index c516ea9..cc2b76a 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 int32_t 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/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/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 468ba2a..8da7eaa 100755
--- a/media/java/android/media/videoeditor/AudioTrack.java
+++ b/media/java/android/media/videoeditor/AudioTrack.java
@@ -18,23 +18,29 @@
import java.io.IOException;
+import android.util.Log;
+
/**
* This class allows to handle an audio track. This audio file is mixed with the
* audio samples of the MediaItems.
* {@hide}
*/
public class AudioTrack {
+ // Logging
+ private static final String TAG = "AudioTrack";
+
// 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;
@@ -47,6 +53,129 @@
// The audio waveform filename
private String mAudioWaveformFilename;
+ private PlaybackThread mPlaybackThread;
+
+ /**
+ * This listener interface is used by the AudioTrack to emit playback
+ * progress notifications.
+ */
+ public interface PlaybackProgressListener {
+ /**
+ * This method notifies the listener of the current time position while
+ * playing an audio track
+ *
+ * @param audioTrack The audio track
+ * @param timeMs The current playback position (expressed in milliseconds
+ * since the beginning of the audio track).
+ * @param end true if the end of the audio track was reached
+ */
+ public void onProgress(AudioTrack audioTrack, long timeMs, boolean end);
+ }
+
+ /**
+ * The playback thread
+ */
+ private class PlaybackThread extends Thread {
+ // Instance variables
+ private final PlaybackProgressListener mListener;
+ private final long mFromMs, mToMs;
+ private boolean mRun;
+ private final boolean mLoop;
+ private long mPositionMs;
+
+ /**
+ * Constructor
+ *
+ * @param fromMs The time (relative to the beginning of the audio track)
+ * at which the playback will start
+ * @param toMs The time (relative to the beginning of the audio track) at
+ * which the playback will stop. Use -1 to play to the end of
+ * the audio track
+ * @param loop true if the playback should be looped once it reaches the
+ * end
+ * @param listener The listener which will be notified of the playback
+ * progress
+ */
+ public PlaybackThread(long fromMs, long toMs, boolean loop,
+ PlaybackProgressListener listener) {
+ mPositionMs = mFromMs = fromMs;
+ if (toMs < 0) {
+ mToMs = mDurationMs;
+ } else {
+ mToMs = toMs;
+ }
+ mLoop = loop;
+ mListener = listener;
+ mRun = true;
+ }
+
+ /*
+ * {@inheritDoc}
+ */
+ @Override
+ public void run() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "===> PlaybackThread.run enter");
+ }
+
+ while (mRun) {
+ try {
+ sleep(100);
+ } catch (InterruptedException ex) {
+ break;
+ }
+
+ mPositionMs += 100;
+
+ if (mPositionMs >= mToMs) {
+ if (!mLoop) {
+ if (mListener != null) {
+ mListener.onProgress(AudioTrack.this, mPositionMs, true);
+ }
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "PlaybackThread.run playback complete");
+ }
+ break;
+ } else {
+ // Fire a notification for the end of the clip
+ if (mListener != null) {
+ mListener.onProgress(AudioTrack.this, mToMs, false);
+ }
+
+ // Rewind
+ mPositionMs = mFromMs;
+ if (mListener != null) {
+ mListener.onProgress(AudioTrack.this, mPositionMs, false);
+ }
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "PlaybackThread.run playback complete");
+ }
+ }
+ } else {
+ if (mListener != null) {
+ mListener.onProgress(AudioTrack.this, mPositionMs, false);
+ }
+ }
+ }
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "===> PlaybackThread.run exit");
+ }
+ }
+
+ /**
+ * Stop the playback
+ *
+ * @return The stop position
+ */
+ public long stopPlayback() {
+ mRun = false;
+ try {
+ join();
+ } catch (InterruptedException ex) {
+ }
+ return mPositionMs;
+ }
+ };
/**
* An object of this type cannot be instantiated by using the default
@@ -59,7 +188,7 @@
/**
* Constructor
- * @param audioTrackId The AudioTrack id
+ * @param audioTrackId The audio track id
* @param filename The absolute file name
*
* @throws IOException if file is not found
@@ -89,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;
@@ -99,7 +231,53 @@
}
/**
- * @return The id of the media item
+ * Constructor
+ *
+ * @param audioTrackId The audio track id
+ * @param filename The audio filename
+ * @param startTimeMs the start time in milliseconds (relative to the
+ * timeline)
+ * @param beginMs start time in the audio track in milliseconds (relative to
+ * the beginning of the audio track)
+ * @param endMs end time in the audio track in milliseconds (relative to the
+ * 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, boolean muted, String audioWaveformFilename) throws IOException {
+ mUniqueId = audioTrackId;
+ mFilename = filename;
+ mStartTimeMs = startTimeMs;
+
+ // TODO: This value represents to the duration of the audio file
+ mDurationMs = 300000;
+
+ // TODO: This value needs to be read from the audio track of the source
+ // file
+ mAudioChannels = 2;
+ mAudioType = MediaProperties.ACODEC_AAC_LC;
+ mAudioBitrate = 128000;
+ mAudioSamplingFrequency = 44100;
+
+ mTimelineDurationMs = endMs - beginMs;
+ mVolumePercent = volume;
+
+ mBeginBoundaryTimeMs = beginMs;
+ mEndBoundaryTimeMs = endMs;
+
+ mLoop = loop;
+ mMuted = muted;
+
+ mAudioWaveformFilename = audioWaveformFilename;
+ }
+
+ /**
+ * @return The id of the audio track
*/
public String getId() {
return mUniqueId;
@@ -169,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.
*
@@ -312,6 +504,50 @@
}
/**
+ * Start the playback of this audio track. This method does not block (does
+ * not wait for the playback to complete).
+ *
+ * @param fromMs The time (relative to the beginning of the audio track) at
+ * which the playback will start
+ * @param toMs The time (relative to the beginning of the audio track) at
+ * which the playback will stop. Use -1 to play to the end of the
+ * audio track
+ * @param loop true if the playback should be looped once it reaches the end
+ * @param listener The listener which will be notified of the playback
+ * progress
+ * @throws IllegalArgumentException if fromMs or toMs is beyond the playback
+ * duration
+ * @throws IllegalStateException if a playback, preview or an export is
+ * already in progress
+ */
+ public void startPlayback(long fromMs, long toMs, boolean loop,
+ PlaybackProgressListener listener) {
+ if (fromMs >= mDurationMs) {
+ return;
+ }
+ mPlaybackThread = new PlaybackThread(fromMs, toMs, loop, listener);
+ mPlaybackThread.start();
+ }
+
+ /**
+ * Stop the audio track playback. This method blocks until the ongoing
+ * playback is stopped.
+ *
+ * @return The accurate current time when stop is effective expressed in
+ * milliseconds
+ */
+ public long stopPlayback() {
+ final long stopTimeMs;
+ if (mPlaybackThread != null) {
+ stopTimeMs = mPlaybackThread.stopPlayback();
+ mPlaybackThread = null;
+ } else {
+ stopTimeMs = 0;
+ }
+ return stopTimeMs;
+ }
+
+ /**
* This API allows to generate a file containing the sample volume levels of
* this audio track object. This function may take significant time and is
* blocking. The filename can be retrieved using getAudioWaveformFilename().
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index 47d4fa0..cc0a155 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -20,7 +20,6 @@
import java.util.List;
import android.graphics.Bitmap;
-import android.media.MediaRecorder;
import android.util.Log;
import android.view.SurfaceHolder;
@@ -50,6 +49,7 @@
private long mBeginBoundaryTimeMs;
private long mEndBoundaryTimeMs;
private int mVolumePercentage;
+ private boolean mMuted;
private String mAudioWaveformFilename;
private PlaybackThread mPlaybackThread;
@@ -207,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);
}
/**
@@ -216,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
@@ -228,7 +236,7 @@
mHeight = 720;
mAspectRatio = MediaProperties.ASPECT_RATIO_3_2;
mFileType = MediaProperties.FILE_MP4;
- mVideoType = MediaRecorder.VideoEncoder.H264;
+ mVideoType = MediaProperties.VCODEC_H264BP;
// Do we have predefined values for this variable?
mVideoProfile = 0;
// Can video and audio duration be different?
@@ -240,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;
}
@@ -540,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/VideoEditorFactory.java b/media/java/android/media/videoeditor/VideoEditorFactory.java
index 8081d76..0a377e2 100755
--- a/media/java/android/media/videoeditor/VideoEditorFactory.java
+++ b/media/java/android/media/videoeditor/VideoEditorFactory.java
@@ -66,11 +66,11 @@
}
}
- Class<?> cls = Class.forName(className);
- Class<?> partypes[] = new Class[1];
+ final Class<?> cls = Class.forName(className);
+ final Class<?> partypes[] = new Class[1];
partypes[0] = String.class;
- Constructor<?> ct = cls.getConstructor(partypes);
- Object arglist[] = new Object[1];
+ final Constructor<?> ct = cls.getConstructor(partypes);
+ final Object arglist[] = new Object[1];
arglist[0] = projectPath;
return (VideoEditor)ct.newInstance(arglist);
@@ -84,6 +84,7 @@
* @param projectPath The path where all VideoEditor internal files
* are stored. When a project is deleted the application is
* responsible for deleting the path and its contents.
+ * @param className The implementation class name
* @param generatePreview if set to true the
* {@link MediaEditor#generatePreview()} will be called internally to
* generate any needed transitions.
@@ -96,8 +97,17 @@
* @throws IllegalStateException if a previous VideoEditor instance has not
* been released
*/
- public static VideoEditor load(String projectPath, boolean generatePreview) throws IOException {
- final VideoEditorTestImpl videoEditor = new VideoEditorTestImpl(projectPath);
+ public static VideoEditor load(String projectPath, String className, boolean generatePreview)
+ throws IOException, ClassNotFoundException, NoSuchMethodException,
+ InvocationTargetException, IllegalAccessException, InstantiationException {
+ final Class<?> cls = Class.forName(className);
+ final Class<?> partypes[] = new Class[1];
+ partypes[0] = String.class;
+ final Constructor<?> ct = cls.getConstructor(partypes);
+ final Object arglist[] = new Object[1];
+ arglist[0] = projectPath;
+
+ final VideoEditor videoEditor = (VideoEditor)ct.newInstance(arglist);
if (generatePreview) {
videoEditor.generatePreview();
}
diff --git a/media/java/android/media/videoeditor/VideoEditorTestImpl.java b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
index 16f9495..b39d9d8 100644
--- a/media/java/android/media/videoeditor/VideoEditorTestImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
@@ -57,6 +57,8 @@
private static final String TAG_OVERLAY_USER_ATTRIBUTES = "overlay_user_attributes";
private static final String TAG_EFFECTS = "effects";
private static final String TAG_EFFECT = "effect";
+ private static final String TAG_AUDIO_TRACKS = "audio_tracks";
+ private static final String TAG_AUDIO_TRACK = "audio_track";
private static final String ATTR_ID = "id";
private static final String ATTR_FILENAME = "filename";
@@ -65,7 +67,8 @@
private static final String ATTR_ASPECT_RATIO = "aspect_ratio";
private static final String ATTR_TYPE = "type";
private static final String ATTR_DURATION = "duration";
- private static final String ATTR_BEGIN_TIME = "start_time";
+ private static final String ATTR_START_TIME = "start_time";
+ private static final String ATTR_BEGIN_TIME = "begin_time";
private static final String ATTR_END_TIME = "end_time";
private static final String ATTR_VOLUME = "volume";
private static final String ATTR_BEHAVIOR = "behavior";
@@ -85,6 +88,8 @@
private static final String ATTR_END_RECT_T = "end_t";
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;
@@ -537,16 +542,13 @@
* {@inheritDoc}
*/
public AudioTrack getAudioTrack(String audioTrackId) {
- if (mPreviewThread != null) {
- throw new IllegalStateException("Previewing is in progress");
+ for (AudioTrack at : mAudioTracks) {
+ if (at.getId().equals(audioTrackId)) {
+ return at;
+ }
}
- final AudioTrack audioTrack = getAudioTrack(audioTrackId);
- if (audioTrack != null) {
- mAudioTracks.remove(audioTrack);
- }
-
- return audioTrack;
+ return null;
}
/*
@@ -581,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());
@@ -703,6 +706,26 @@
}
serializer.endTag("", TAG_TRANSITIONS);
+ serializer.startTag("", TAG_AUDIO_TRACKS);
+ for (AudioTrack at : mAudioTracks) {
+ serializer.startTag("", TAG_AUDIO_TRACK);
+ serializer.attribute("", ATTR_ID, at.getId());
+ serializer.attribute("", ATTR_FILENAME, at.getFilename());
+ serializer.attribute("", ATTR_START_TIME, Long.toString(at.getStartTime()));
+ 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,
+ at.getAudioWaveformFilename());
+ }
+
+ serializer.endTag("", TAG_AUDIO_TRACK);
+ }
+ serializer.endTag("", TAG_AUDIO_TRACKS);
+
serializer.endTag("", TAG_PROJECT);
serializer.endDocument();
@@ -745,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));
@@ -795,6 +827,11 @@
currentMediaItem.addEffect(effect);
}
}
+ } else if (TAG_AUDIO_TRACK.equals(name)) {
+ final AudioTrack audioTrack = parseAudioTrack(parser);
+ if (audioTrack != null) {
+ addAudioTrack(audioTrack);
+ }
}
break;
}
@@ -962,6 +999,33 @@
return effect;
}
+ /**
+ * Parse the audio track
+ *
+ * @param parser The parser
+ *
+ * @return The audio track
+ */
+ private AudioTrack parseAudioTrack(XmlPullParser parser) {
+ final String audioTrackId = parser.getAttributeValue("", ATTR_ID);
+ final String filename = parser.getAttributeValue("", ATTR_FILENAME);
+ final long startTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_START_TIME));
+ 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, muted, waveformFilename);
+
+ return audioTrack;
+ } catch (IOException ex) {
+ return null;
+ }
+ }
+
public void cancelExport(String filename) {
}
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/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));
}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 90a6256..1d6b18d 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -782,7 +782,6 @@
const String16 translatable16("translatable");
const String16 formatted16("formatted");
const String16 false16("false");
- const String16 product16("product");
const String16 myPackage(assets->getPackage());
@@ -830,7 +829,6 @@
bool curIsStyled = false;
bool curIsPseudolocalizable = false;
bool curIsFormatted = fileIsTranslatable;
- String16 curProduct;
bool localHasErrors = false;
if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
@@ -1228,8 +1226,6 @@
translatable.setTo(block.getAttributeStringValue(i, &length));
} else if (strcmp16(attr, formatted16.string()) == 0) {
formatted.setTo(block.getAttributeStringValue(i, &length));
- } else if (strcmp16(attr, product16.string()) == 0) {
- curProduct.setTo(block.getAttributeStringValue(i, &length));
}
}
@@ -1356,6 +1352,12 @@
hasErrors = localHasErrors = true;
}
+ String16 product;
+ identIdx = block.indexOfAttribute(NULL, "product");
+ if (identIdx >= 0) {
+ product = String16(block.getAttributeStringValue(identIdx, &len));
+ }
+
String16 comment(block.getComment(&len) ? block.getComment(&len) : nulStr);
if (curIsBag) {
@@ -1447,7 +1449,7 @@
err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
ident, parentIdent, itemIdent, curFormat, curIsFormatted,
- curProduct, false, overwrite, outTable);
+ product, false, overwrite, outTable);
if (err == NO_ERROR) {
if (curIsPseudolocalizable && localeIsDefined(curParams)
&& bundle->getPseudolocalize()) {
@@ -1456,7 +1458,7 @@
block.setPosition(parserPosition);
err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
curType, ident, parentIdent, itemIdent, curFormat,
- curIsFormatted, curProduct, true, overwrite, outTable);
+ curIsFormatted, product, true, overwrite, outTable);
#endif
}
}
@@ -1480,7 +1482,7 @@
err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
*curTag, curIsStyled, curFormat, curIsFormatted,
- curProduct, false, overwrite, outTable);
+ product, false, overwrite, outTable);
if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
hasErrors = localHasErrors = true;
@@ -1492,7 +1494,7 @@
block.setPosition(parserPosition);
err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
ident, *curTag, curIsStyled, curFormat,
- curIsFormatted, curProduct,
+ curIsFormatted, product,
true, overwrite, outTable);
if (err != NO_ERROR) {
hasErrors = localHasErrors = true;