Merge "Report WPS overlap error" into honeycomb
diff --git a/api/current.xml b/api/current.xml
index 7e2ac7e..4989eba 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -137540,6 +137540,34 @@
<parameter name="params" type="Params...">
</parameter>
</method>
+<method name="execute"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="runnable" type="java.lang.Runnable">
+</parameter>
+</method>
+<method name="executeOnExecutor"
+ return="android.os.AsyncTask<Params, Progress, Result>"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="exec" type="java.util.concurrent.Executor">
+</parameter>
+<parameter name="params" type="Params...">
+</parameter>
+</method>
<method name="get"
return="Result"
abstract="false"
@@ -137672,6 +137700,16 @@
<parameter name="values" type="Progress...">
</parameter>
</method>
+<field name="THREAD_POOL_EXECUTOR"
+ type="java.util.concurrent.ThreadPoolExecutor"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="AsyncTask.Status"
extends="java.lang.Enum"
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 3212cba..d038cd6 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -18,7 +18,6 @@
import android.util.Log;
-import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -29,8 +28,6 @@
* are then determined internally and the animation will call these functions as necessary to
* animate the property.
*
- * <p class="note"><b>Note:</b> Instances of this class hold only a {@link WeakReference}
- * to the target object.</p>
* @see #setPropertyName(String)
*
*/
@@ -38,7 +35,7 @@
private static final boolean DBG = false;
// The target object on which the property exists, set in the constructor
- private WeakReference<Object> mTargetRef;
+ private Object mTarget;
private String mPropertyName;
@@ -105,9 +102,6 @@
* @return Method the method associated with mPropertyName.
*/
private Method getPropertyFunction(String prefix, Class valueType) {
- final Object target = mTargetRef == null ? null : mTargetRef.get();
- if (target == null) return null;
-
// TODO: faster implementation...
Method returnVal = null;
String firstLetter = mPropertyName.substring(0, 1);
@@ -120,7 +114,7 @@
args[0] = valueType;
}
try {
- returnVal = target.getClass().getMethod(setterName, args);
+ returnVal = mTarget.getClass().getMethod(setterName, args);
} catch (NoSuchMethodException e) {
Log.e("ObjectAnimator",
"Couldn't find setter/getter for property " + mPropertyName + ": " + e);
@@ -140,14 +134,13 @@
* A constructor that takes a single property name and set of values. This constructor is
* used in the simple case of animating a single property.
*
- * @param target The object whose property is to be animated. It will be weakly referenced
- * from the newly-created ObjectAnimator. This object should have a public method on it called
- * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
- * parameter.
+ * @param target The object whose property is to be animated. This object should
+ * have a public method on it called <code>setName()</code>, where <code>name</code> is
+ * the value of the <code>propertyName</code> parameter.
* @param propertyName The name of the property being animated.
*/
private ObjectAnimator(Object target, String propertyName) {
- mTargetRef = new WeakReference<Object>(target);
+ mTarget = target;
setPropertyName(propertyName);
}
@@ -159,10 +152,9 @@
* from the target object and property being animated). Therefore, there should typically
* be two or more values.
*
- * @param target The object whose property is to be animated. It will be weakly referenced
- * from the newly-created ObjectAnimator. This object should have a public method on it called
- * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
- * parameter.
+ * @param target The object whose property is to be animated. This object should
+ * have a public method on it called <code>setName()</code>, where <code>name</code> is
+ * the value of the <code>propertyName</code> parameter.
* @param propertyName The name of the property being animated.
* @param values A set of values that the animation will animate between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
@@ -181,10 +173,9 @@
* from the target object and property being animated). Therefore, there should typically
* be two or more values.
*
- * @param target The object whose property is to be animated. It will be weakly referenced
- * from the newly-created ObjectAnimator. This object should have a public method on it called
- * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
- * parameter.
+ * @param target The object whose property is to be animated. This object should
+ * have a public method on it called <code>setName()</code>, where <code>name</code> is
+ * the value of the <code>propertyName</code> parameter.
* @param propertyName The name of the property being animated.
* @param values A set of values that the animation will animate between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
@@ -201,10 +192,10 @@
* PropertyValuesHolder allows you to associate a set of animation values with a property
* name.
*
- * @param target The object whose property is to be animated. It will be weakly referenced
- * from the newly-created ObjectAnimator. This object should have public methods on it called
- * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the
- * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects.
+ * @param target The object whose property is to be animated. This object should
+ * have public methods on it called <code>setName()</code>, where <code>name</code> is
+ * the name of the property passed in as the <code>propertyName</code> parameter for
+ * each of the PropertyValuesHolder objects.
* @param propertyName The name of the property being animated.
* @param evaluator A TypeEvaluator that will be called on each animation frame to
* provide the ncessry interpolation between the Object values to derive the animated
@@ -227,10 +218,10 @@
* PropertyValuesHolder allows you to associate a set of animation values with a property
* name.
*
- * @param target The object whose property is to be animated. It will be weakly referenced
- * from the newly-created ObjectAnimator. This object should have public methods on it called
- * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the
- * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects.
+ * @param target The object whose property is to be animated. This object should
+ * have public methods on it called <code>setName()</code>, where <code>name</code> is
+ * the name of the property passed in as the <code>propertyName</code> parameter for
+ * each of the PropertyValuesHolder objects.
* @param values A set of PropertyValuesHolder objects whose values will be animated
* between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
@@ -238,7 +229,7 @@
public static ObjectAnimator ofPropertyValuesHolder(Object target,
PropertyValuesHolder... values) {
ObjectAnimator anim = new ObjectAnimator();
- anim.mTargetRef = new WeakReference<Object>(target);
+ anim.mTarget = target;
anim.setValues(values);
return anim;
}
@@ -279,8 +270,7 @@
@Override
public void start() {
if (DBG) {
- final Object target = mTargetRef == null ? null : mTargetRef.get();
- Log.d("ObjectAnimator", "Anim target, duration" + target + ", " + getDuration());
+ Log.d("ObjectAnimator", "Anim target, duration" + mTarget + ", " + getDuration());
for (int i = 0; i < mValues.length; ++i) {
PropertyValuesHolder pvh = mValues[i];
ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes;
@@ -307,14 +297,11 @@
@Override
void initAnimation() {
if (!mInitialized) {
- final Object target = mTargetRef == null ? null : mTargetRef.get();
- if (target == null) return;
-
// mValueType may change due to setter/getter setup; do this before calling super.init(),
// which uses mValueType to set up the default type evaluator.
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setupSetterAndGetter(target);
+ mValues[i].setupSetterAndGetter(mTarget);
}
super.initAnimation();
}
@@ -339,26 +326,23 @@
/**
* The target object whose property will be animated by this animation
*
- * @return The object being animated, or null if the object has been garbage collected.
+ * @return The object being animated
*/
public Object getTarget() {
- return mTargetRef == null ? null : mTargetRef.get();
+ return mTarget;
}
/**
- * Sets the target object whose property will be animated by this animation. The target
- * will be weakly referenced from this object.
+ * Sets the target object whose property will be animated by this animation
*
* @param target The object being animated
*/
@Override
public void setTarget(Object target) {
- final Object currentTarget = mTargetRef == null ? null : mTargetRef.get();
-
- if (currentTarget != target) {
- mTargetRef = new WeakReference<Object>(target);
- if (currentTarget != null && target != null
- && currentTarget.getClass() == target.getClass()) {
+ if (mTarget != target) {
+ final Object oldTarget = mTarget;
+ mTarget = target;
+ if (oldTarget != null && target != null && oldTarget.getClass() == target.getClass()) {
return;
}
// New target type should cause re-initialization prior to starting
@@ -368,25 +352,19 @@
@Override
public void setupStartValues() {
- final Object target = mTargetRef == null ? null : mTargetRef.get();
- if (target == null) return;
-
initAnimation();
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setupStartValue(target);
+ mValues[i].setupStartValue(mTarget);
}
}
@Override
public void setupEndValues() {
- final Object target = mTargetRef == null ? null : mTargetRef.get();
- if (target == null) return;
-
initAnimation();
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setupEndValue(target);
+ mValues[i].setupEndValue(mTarget);
}
}
@@ -405,13 +383,9 @@
@Override
void animateValue(float fraction) {
super.animateValue(fraction);
-
- final Object target = mTargetRef == null ? null : mTargetRef.get();
- if (target == null) return;
-
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setAnimatedValue(target);
+ mValues[i].setAnimatedValue(mTarget);
}
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 17131d2..2d95781 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -281,9 +281,11 @@
* Value for {@link #flags}: Set to true if the application has been
* installed using the forward lock option.
*
+ * NOTE: DO NOT CHANGE THIS VALUE! It is saved in packages.xml.
+ *
* {@hide}
*/
- public static final int FLAG_FORWARD_LOCK = 1<<30;
+ public static final int FLAG_FORWARD_LOCK = 1<<29;
/**
* Value for {@link #flags}: set to <code>true</code> if the application
@@ -296,7 +298,7 @@
*
* {@hide}
*/
- public static final int FLAG_CANT_SAVE_STATE = 1<<29;
+ public static final int FLAG_CANT_SAVE_STATE = 1<<28;
/**
* Flags associated with the application. Any combination of
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 9f7e31c..5a35eb0 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -16,9 +16,11 @@
package android.os;
+import java.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
+import java.util.concurrent.Executor;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
@@ -151,8 +153,6 @@
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
- private static final BlockingQueue<Runnable> sWorkQueue =
- new LinkedBlockingQueue<Runnable>(10);
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
@@ -162,8 +162,17 @@
}
};
- private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
- MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);
+ private static final BlockingQueue<Runnable> sPoolWorkQueue =
+ new LinkedBlockingQueue<Runnable>(10);
+
+ /**
+ * A {@link ThreadPoolExecutor} that can be used to execute tasks in parallel.
+ */
+ public static final ThreadPoolExecutor THREAD_POOL_EXECUTOR
+ = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
+ TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
+
+ private static final SerialExecutor sSerialExecutor = new SerialExecutor();
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
@@ -177,6 +186,32 @@
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
+ private static class SerialExecutor implements Executor {
+ final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
+ Runnable mActive;
+
+ public synchronized void execute(final Runnable r) {
+ mTasks.offer(new Runnable() {
+ public void run() {
+ try {
+ r.run();
+ } finally {
+ scheduleNext();
+ }
+ }
+ });
+ if (mActive == null) {
+ scheduleNext();
+ }
+ }
+
+ protected synchronized void scheduleNext() {
+ if ((mActive = mTasks.poll()) != null) {
+ THREAD_POOL_EXECUTOR.execute(mActive);
+ }
+ }
+ }
+
/**
* Indicates the current status of the task. Each status will be set only once
* during the lifetime of a task.
@@ -433,7 +468,11 @@
/**
* Executes the task with the specified parameters. The task returns
- * itself (this) so that the caller can keep a reference to it.
+ * itself (this) so that the caller can keep a reference to it. The tasks
+ * started by all invocations of this method in a given process are run
+ * sequentially. Call the executeOnExecutor(Executor,Params...)
+ * with a custom {@link Executor} to have finer grained control over how the
+ * tasks are run.
*
* This method must be invoked on the UI thread.
*
@@ -445,6 +484,26 @@
* {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
*/
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
+ return executeOnExecutor(sSerialExecutor, params);
+ }
+
+ /**
+ * Executes the task with the specified parameters. The task returns
+ * itself (this) so that the caller can keep a reference to it.
+ *
+ * This method must be invoked on the UI thread.
+ *
+ * @param exec The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a
+ * convenient process-wide thread pool for tasks that are loosely coupled.
+ * @param params The parameters of the task.
+ *
+ * @return This instance of AsyncTask.
+ *
+ * @throws IllegalStateException If {@link #getStatus()} returns either
+ * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
+ */
+ public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
+ Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
@@ -462,12 +521,20 @@
onPreExecute();
mWorker.mParams = params;
- sExecutor.execute(mFuture);
+ exec.execute(mFuture);
return this;
}
/**
+ * Schedules the {@link Runnable} in serial with the other AsyncTasks that were started
+ * with {@link #execute}.
+ */
+ public static void execute(Runnable runnable) {
+ sSerialExecutor.execute(runnable);
+ }
+
+ /**
* This method can be invoked from {@link #doInBackground} to
* publish updates on the UI thread while the background computation is
* still running. Each call to this method will trigger the execution of
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index ad9e6863..e228537 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1780,7 +1780,7 @@
}
void dispatchDetachedFromWindow() {
- if (mView != null) {
+ if (mView != null && mView.mAttachInfo != null) {
mView.dispatchDetachedFromWindow();
}
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index 3d21048..472a335 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -22,7 +22,6 @@
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -212,6 +211,9 @@
.getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorLeft, 0);
mIndicatorRight = a
.getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorRight, 0);
+ if (mIndicatorRight == 0) {
+ mIndicatorRight = mIndicatorLeft + mGroupIndicator.getIntrinsicWidth();
+ }
mChildIndicatorLeft = a.getDimensionPixelSize(
com.android.internal.R.styleable.ExpandableListView_childIndicatorLeft, CHILD_INDICATOR_INHERIT);
mChildIndicatorRight = a.getDimensionPixelSize(
diff --git a/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml b/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml
index 8a46546..4f5beff 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml
@@ -27,12 +27,11 @@
android:layout_height="0px"
android:layout_weight="1"
android:layout_above="@+id/emergencyCall">
- <RelativeLayout
+ <RelativeLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
-
- <TextView
+ android:layout_height="match_parent">
+
+ <TextView
android:id="@+id/topHeader"
android:layout_width="match_parent"
android:layout_height="64dip"
@@ -43,7 +42,7 @@
android:drawableLeft="@drawable/ic_lock_idle_lock"
android:drawablePadding="5dip"
/>
-
+
<!-- spacer below header -->
<View
android:id="@+id/spacerTop"
@@ -51,7 +50,7 @@
android:layout_height="1dip"
android:layout_below="@id/topHeader"
android:background="@drawable/divider_horizontal_dark"/>
-
+
<TextView
android:id="@+id/instructions"
android:layout_width="match_parent"
@@ -62,7 +61,7 @@
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@android:string/lockscreen_glogin_instructions"
/>
-
+
<EditText
android:id="@+id/login"
android:layout_width="match_parent"
@@ -74,7 +73,7 @@
android:hint="@android:string/lockscreen_glogin_username_hint"
android:inputType="textEmailAddress"
/>
-
+
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
@@ -88,11 +87,11 @@
android:nextFocusRight="@+id/ok"
android:nextFocusDown="@+id/ok"
/>
-
+
<!-- ok below password, aligned to right of screen -->
<Button
android:id="@+id/ok"
- android:layout_width="85dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/password"
android:layout_marginTop="7dip"
@@ -100,10 +99,10 @@
android:layout_alignParentRight="true"
android:text="@android:string/lockscreen_glogin_submit_button"
/>
-
+
</RelativeLayout>
</ScrollView>
-
+
<!-- spacer above emergency call -->
<View
android:layout_width="match_parent"
@@ -121,6 +120,7 @@
android:drawableLeft="@drawable/ic_emergency"
android:drawablePadding="8dip"
android:text="@android:string/lockscreen_emergency_call"
+ android:visibility="gone"
/>
</LinearLayout>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index f65b1f2..744d0d8 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -114,7 +114,7 @@
?android:attr/expandableListPreferredItemPaddingLeft</item>
<item name="expandableListPreferredItemIndicatorLeft">3dip</item>
- <item name="expandableListPreferredItemIndicatorRight">33dip</item>
+ <item name="expandableListPreferredItemIndicatorRight">0dip</item>
<item name="expandableListPreferredChildIndicatorLeft">
?android:attr/expandableListPreferredItemIndicatorLeft</item>
<item name="expandableListPreferredChildIndicatorRight">
@@ -816,7 +816,7 @@
?android:attr/expandableListPreferredItemPaddingLeft</item>
<item name="expandableListPreferredItemIndicatorLeft">3dip</item>
- <item name="expandableListPreferredItemIndicatorRight">33dip</item>
+ <item name="expandableListPreferredItemIndicatorRight">0dip</item>
<item name="expandableListPreferredChildIndicatorLeft">
?android:attr/expandableListPreferredItemIndicatorLeft</item>
<item name="expandableListPreferredChildIndicatorRight">
@@ -1075,7 +1075,7 @@
?android:attr/expandableListPreferredItemPaddingLeft</item>
<item name="expandableListPreferredItemIndicatorLeft">3dip</item>
- <item name="expandableListPreferredItemIndicatorRight">33dip</item>
+ <item name="expandableListPreferredItemIndicatorRight">0dip</item>
<item name="expandableListPreferredChildIndicatorLeft">
?android:attr/expandableListPreferredItemIndicatorLeft</item>
<item name="expandableListPreferredChildIndicatorRight">
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index bdd8e73..71ec760 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -37,6 +37,10 @@
// Turn on to display vertex and tex coords data about 9patch objects
// This flag requires DEBUG_PATCHES to be turned on
#define DEBUG_PATCHES_VERTICES 0
+// Turn on to display vertex and tex coords data used by empty quads
+// in 9patch objects
+// This flag requires DEBUG_PATCHES to be turned on
+#define DEBUG_PATCHES_EMPTY_VERTICES 0
// Turn on to display debug info about paths
#define DEBUG_PATHS 0
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index cd2554e..e6bea78 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -29,10 +29,6 @@
void LayerRenderer::prepare(bool opaque) {
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo);
-#if RENDER_LAYERS_AS_REGIONS
- mLayer->region.clear();
-#endif
-
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &mPreviousFbo);
glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
@@ -78,6 +74,7 @@
mLayer->meshIndices = NULL;
mLayer->meshElementCount = 0;
}
+ mLayer->region.clear();
return;
}
@@ -129,6 +126,8 @@
indices[index + 4] = quad + 1; // top-right
indices[index + 5] = quad + 3; // bottom-right
}
+
+ mLayer->region.clear();
#endif
}
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index e5cb67b..77cbb80 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -212,7 +212,7 @@
}
float u2 = fmax(0.0f, stepX - 0.5f) / bitmapWidth;
- generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount);
+ bool valid = generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount);
x1 = x2;
u1 = (stepX + 0.5f) / bitmapWidth;
@@ -223,17 +223,22 @@
generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2, quadCount);
}
-void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
+bool Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
float u1, float v1, float u2, float v2, uint32_t& quadCount) {
const uint32_t oldQuadCount = quadCount;
- const bool valid = x2 - x1 > 0.9999f && y2 - y1 > 0.9999f;
+ const bool valid = x2 >= x1 && y2 >= y1;
if (valid) {
quadCount++;
}
// Skip degenerate and transparent (empty) quads
if (!valid || ((mColorKey >> oldQuadCount) & 0x1) == 1) {
- return;
+#if DEBUG_PATCHES_EMPTY_VERTICES
+ PATCH_LOGD(" quad %d (empty)", oldQuadCount);
+ PATCH_LOGD(" left, top = %.2f, %.2f\t\tu1, v1 = %.2f, %.2f", x1, y1, u1, v1);
+ PATCH_LOGD(" right, bottom = %.2f, %.2f\t\tu2, v2 = %.2f, %.2f", x2, y2, u2, v2);
+#endif
+ return false;
}
#if RENDER_LAYERS_AS_REGIONS
@@ -262,6 +267,8 @@
PATCH_LOGD(" left, top = %.2f, %.2f\t\tu1, v1 = %.2f, %.2f", x1, y1, u1, v1);
PATCH_LOGD(" right, bottom = %.2f, %.2f\t\tu2, v2 = %.2f, %.2f", x2, y2, u2, v2);
#endif
+
+ return true;
}
}; // namespace uirenderer
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 0f0ffa2..45ce998 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -71,7 +71,7 @@
void generateRow(TextureVertex*& vertex, float y1, float y2,
float v1, float v2, float stretchX, float width, float bitmapWidth,
uint32_t& quadCount);
- void generateQuad(TextureVertex*& vertex,
+ bool generateQuad(TextureVertex*& vertex,
float x1, float y1, float x2, float y2,
float u1, float v1, float u2, float v2,
uint32_t& quadCount);
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
index aa4cf2d..4615e1f 100644
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
@@ -56,7 +56,7 @@
}
//sliao
-uchar3 convert2uchar3(float3 xyz);
+extern uchar3 __attribute__((overloadable)) convert2uchar3(float3 xyz);
void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
uchar4 *output = (uchar4 *)v_out;
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 2ed7774..6e4c22e 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -188,12 +188,7 @@
isFirstUpload = true;
}
- GLenum target = (GLenum)getGLTarget();
- if (target == GL_TEXTURE_2D) {
- upload2DTexture(isFirstUpload, mPtr);
- } else if (target == GL_TEXTURE_CUBE_MAP) {
- uploadCubeTexture(isFirstUpload);
- }
+ upload2DTexture(isFirstUpload);
if (!(mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
freeScriptMemory();
@@ -202,6 +197,15 @@
rsc->checkError("Allocation::uploadToTexture");
}
+const static GLenum gFaceOrder[] = {
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+};
+
void Allocation::update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
uint32_t lod, RsAllocationCubemapFace face,
uint32_t w, uint32_t h) {
@@ -210,10 +214,14 @@
GLenum target = (GLenum)getGLTarget();
glBindTexture(target, mTextureID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexSubImage2D(GL_TEXTURE_2D, lod, xoff, yoff, w, h, format, type, ptr);
+ GLenum t = GL_TEXTURE_2D;
+ if (mType->getDimFaces()) {
+ t = gFaceOrder[face];
+ }
+ glTexSubImage2D(t, lod, xoff, yoff, w, h, format, type, ptr);
}
-void Allocation::upload2DTexture(bool isFirstUpload, const void *ptr) {
+void Allocation::upload2DTexture(bool isFirstUpload) {
GLenum type = mType->getElement()->getComponent().getGLType();
GLenum format = mType->getElement()->getComponent().getGLFormat();
@@ -221,62 +229,29 @@
glBindTexture(target, mTextureID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- for (uint32_t lod = 0; lod < mType->getLODCount(); lod++) {
- const uint8_t *p = (const uint8_t *)ptr;
- p += mType->getLODOffset(lod);
-
- if (isFirstUpload) {
- glTexImage2D(GL_TEXTURE_2D, lod, format,
- mType->getLODDimX(lod), mType->getLODDimY(lod),
- 0, format, type, p);
- } else {
- glTexSubImage2D(GL_TEXTURE_2D, lod, 0, 0,
- mType->getLODDimX(lod), mType->getLODDimY(lod),
- format, type, p);
- }
+ uint32_t faceCount = 1;
+ if (mType->getDimFaces()) {
+ faceCount = 6;
}
- if (mMipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
-#ifndef ANDROID_RS_BUILD_FOR_HOST
- glGenerateMipmap(target);
-#endif //ANDROID_RS_BUILD_FOR_HOST
- }
-}
-
-void Allocation::uploadCubeTexture(bool isFirstUpload) {
- GLenum type = mType->getElement()->getComponent().getGLType();
- GLenum format = mType->getElement()->getComponent().getGLFormat();
-
- GLenum target = (GLenum)getGLTarget();
- glBindTexture(target, mTextureID);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- GLenum faceOrder[] = {
- GL_TEXTURE_CUBE_MAP_POSITIVE_X,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
- };
-
- Adapter2D adapt(getContext(), this);
- for (uint32_t face = 0; face < 6; face ++) {
- adapt.setFace(face);
-
+ for (uint32_t face = 0; face < faceCount; face ++) {
for (uint32_t lod = 0; lod < mType->getLODCount(); lod++) {
- adapt.setLOD(lod);
+ const uint8_t *p = (const uint8_t *)mPtr;
+ p += mType->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0);
- uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
+ GLenum t = GL_TEXTURE_2D;
+ if (mType->getDimFaces()) {
+ t = gFaceOrder[face];
+ }
if (isFirstUpload) {
- glTexImage2D(faceOrder[face], lod, format,
- adapt.getDimX(), adapt.getDimY(),
- 0, format, type, ptr);
+ glTexImage2D(t, lod, format,
+ mType->getLODDimX(lod), mType->getLODDimY(lod),
+ 0, format, type, p);
} else {
- glTexSubImage2D(faceOrder[face], lod, 0, 0,
- adapt.getDimX(), adapt.getDimY(),
- format, type, ptr);
+ glTexSubImage2D(t, lod, 0, 0,
+ mType->getLODDimX(lod), mType->getLODDimY(lod),
+ format, type, p);
}
}
}
@@ -364,7 +339,7 @@
if (mPtr) {
const uint8_t *src = static_cast<const uint8_t *>(data);
uint8_t *dst = static_cast<uint8_t *>(mPtr);
- dst += mType->getLODOffset(lod, xoff, yoff);
+ dst += mType->getLODFaceOffset(lod, face, xoff, yoff);
//LOGE(" %p %p %i ", dst, src, eSize);
for (uint32_t line=yoff; line < (yoff+h); line++) {
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index a160765..4f5d5a8 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -105,9 +105,6 @@
return mMipmapControl != RS_ALLOCATION_MIPMAP_NONE;
}
- void upload2DTexture(bool isFirstUpload, const void *ptr);
- void update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
- uint32_t lod, RsAllocationCubemapFace face, uint32_t w, uint32_t h);
protected:
ObjectBaseRef<const Type> mType;
@@ -149,7 +146,9 @@
private:
void init(Context *rsc, const Type *);
- void uploadCubeTexture(bool isFirstUpload);
+ void upload2DTexture(bool isFirstUpload);
+ void update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
+ uint32_t lod, RsAllocationCubemapFace face, uint32_t w, uint32_t h);
void allocScriptMemory();
void freeScriptMemory();
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 0ecb18a..1ab2109 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -490,7 +490,8 @@
if (bccLinkBC(s->mBccScript,
resName,
NULL /*rs_runtime_lib_bc*/,
- 0 /*rs_runtime_lib_bc_size*/,
+ 1 /*rs_runtime_lib_bc_size*/
+ /*"1" means skip buffer here, and let libbcc decide*/,
0) != 0) {
LOGE("bcc: FAILS to link bitcode");
// Handle Fatal Error
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 670ea33..d7b5f12 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -132,6 +132,17 @@
return offset;
}
+uint32_t Type::getLODFaceOffset(uint32_t lod, RsAllocationCubemapFace face, uint32_t x, uint32_t y) const {
+ uint32_t offset = mLODs[lod].mOffset;
+ offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes();
+
+ if (face != 0) {
+ uint32_t faceOffset = getSizeBytes() / 6;
+ offset += faceOffset * face;
+ }
+ return offset;
+}
+
void Type::dumpLOGV(const char *prefix) const {
char buf[1024];
ObjectBase::dumpLOGV(prefix);
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 34498f0..90ae039 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -44,12 +44,14 @@
uint32_t getLODDimX(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mX;}
uint32_t getLODDimY(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mY;}
uint32_t getLODDimZ(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mZ;}
- uint32_t getLODOffset(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mOffset;}
+ uint32_t getLODOffset(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mOffset;}
uint32_t getLODOffset(uint32_t lod, uint32_t x) const;
uint32_t getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const;
uint32_t getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const;
+ uint32_t getLODFaceOffset(uint32_t lod, RsAllocationCubemapFace face, uint32_t x, uint32_t y) const;
+
uint32_t getLODCount() const {return mLODCount;}
bool getIsNp2() const;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
index da60f0d..1b2fcad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.AsyncTask;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
@@ -78,15 +79,19 @@
// TODO: Fix this racy API by adding something better to TelephonyManager or
// ConnectivityService.
- private void unsafe(boolean enabled) {
- Settings.System.putInt(
- mContext.getContentResolver(),
- Settings.System.AIRPLANE_MODE_ON,
- enabled ? 1 : 0);
- Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra("state", enabled);
- mContext.sendBroadcast(intent);
+ private void unsafe(final boolean enabled) {
+ AsyncTask.execute(new Runnable() {
+ public void run() {
+ Settings.System.putInt(
+ mContext.getContentResolver(),
+ Settings.System.AIRPLANE_MODE_ON,
+ enabled ? 1 : 0);
+ Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.putExtra("state", enabled);
+ mContext.sendBroadcast(intent);
+ }
+ });
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
index 866e5fc..b0a6d7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
@@ -18,6 +18,7 @@
import android.content.ContentResolver;
import android.content.Context;
+import android.os.AsyncTask;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
@@ -45,7 +46,6 @@
}
public void onCheckedChanged(CompoundButton view, boolean checked) {
- Slog.d(TAG, "onCheckedChanged checked=" + checked + " mLockRotation=" + mLockRotation);
if (checked != mLockRotation) {
setLockRotation(checked);
}
@@ -56,18 +56,22 @@
return 0 == Settings.System.getInt(cr, Settings.System.ACCELEROMETER_ROTATION, 0);
}
- private void setLockRotation(boolean locked) {
+ private void setLockRotation(final boolean locked) {
mLockRotation = locked;
- try {
- IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService(
- Context.WINDOW_SERVICE));
- ContentResolver cr = mContext.getContentResolver();
- if (locked) {
- wm.freezeRotation();
- } else {
- wm.thawRotation();
- }
- } catch (RemoteException exc) {
- }
+ AsyncTask.execute(new Runnable() {
+ public void run() {
+ try {
+ IWindowManager wm = IWindowManager.Stub.asInterface(
+ ServiceManager.getService(Context.WINDOW_SERVICE));
+ ContentResolver cr = mContext.getContentResolver();
+ if (locked) {
+ wm.freezeRotation();
+ } else {
+ wm.thawRotation();
+ }
+ } catch (RemoteException exc) {
+ }
+ }
+ });
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
index ca1d98f..521467a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
@@ -18,6 +18,7 @@
import android.content.ContentResolver;
import android.content.Context;
+import android.os.AsyncTask;
import android.os.IPowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -79,11 +80,15 @@
setMode(automatic ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC
: Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
if (!automatic) {
- value = value + value + MINIMUM_BACKLIGHT;
- setBrightness(value);
+ final int val = value + value + MINIMUM_BACKLIGHT;
+ setBrightness(val);
if (!tracking) {
- Settings.System.putInt(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS, value);
+ AsyncTask.execute(new Runnable() {
+ public void run() {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS, val);
+ }
+ });
}
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 2a39322..6b559cf 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -191,9 +191,6 @@
static final int APPLICATION_PANEL_SUBLAYER = 1;
static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
- // Debugging: set this to have the system act like there is no hard keyboard.
- static final boolean KEYBOARD_ALWAYS_HIDDEN = false;
-
static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -914,38 +911,44 @@
}
private int determineHiddenState(int mode, int hiddenValue, int visibleValue) {
- if (KEYBOARD_ALWAYS_HIDDEN) {
- return hiddenValue;
- }
- if (mLidOpen == LID_ABSENT) {
- return visibleValue;
- }
-
- switch (mode) {
- case 1:
- return mLidOpen == LID_OPEN ? visibleValue : hiddenValue;
- case 2:
- return mLidOpen == LID_OPEN ? hiddenValue : visibleValue;
+ if (mLidOpen != LID_ABSENT) {
+ switch (mode) {
+ case 1:
+ return mLidOpen == LID_OPEN ? visibleValue : hiddenValue;
+ case 2:
+ return mLidOpen == LID_OPEN ? hiddenValue : visibleValue;
+ }
}
return visibleValue;
}
-
+
/** {@inheritDoc} */
public void adjustConfigurationLw(Configuration config) {
readLidState();
+
mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN);
- config.hardKeyboardHidden = determineHiddenState(
- mLidKeyboardAccessibility, Configuration.HARDKEYBOARDHIDDEN_YES,
- Configuration.HARDKEYBOARDHIDDEN_NO);
- config.navigationHidden = determineHiddenState(
- mLidNavigationAccessibility, Configuration.NAVIGATIONHIDDEN_YES,
- Configuration.NAVIGATIONHIDDEN_NO);
- config.keyboardHidden = (config.hardKeyboardHidden
- == Configuration.HARDKEYBOARDHIDDEN_NO || mHasSoftInput)
- ? Configuration.KEYBOARDHIDDEN_NO
- : Configuration.KEYBOARDHIDDEN_YES;
+
+ if (config.keyboard == Configuration.KEYBOARD_NOKEYS) {
+ config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
+ } else {
+ config.hardKeyboardHidden = determineHiddenState(mLidKeyboardAccessibility,
+ Configuration.HARDKEYBOARDHIDDEN_YES, Configuration.HARDKEYBOARDHIDDEN_NO);
+ }
+
+ if (config.navigation == Configuration.NAVIGATION_NONAV) {
+ config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
+ } else {
+ config.navigationHidden = determineHiddenState(mLidNavigationAccessibility,
+ Configuration.NAVIGATIONHIDDEN_YES, Configuration.NAVIGATIONHIDDEN_NO);
+ }
+
+ if (mHasSoftInput || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
+ config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
+ } else {
+ config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
+ }
}
-
+
/** {@inheritDoc} */
public int windowTypeToLayerLw(int type) {
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index e73afa0..7099ab5 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -25,6 +25,16 @@
android:hardwareAccelerated="true">
<activity
+ android:name="SimplePatchActivity"
+ android:label="_SimplePatch"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="ViewLayersActivity"
android:label="_ViewLayers">
<intent-filter>
diff --git a/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_maximized.9.png b/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_maximized.9.png
new file mode 100644
index 0000000..d5c3276
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_maximized.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_minimized.9.png b/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_minimized.9.png
new file mode 100644
index 0000000..4515b42
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_minimized.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SimplePatchActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/SimplePatchActivity.java
new file mode 100644
index 0000000..a9b4d1c
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/SimplePatchActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class SimplePatchActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(new PatchView(this));
+ }
+
+ private static class PatchView extends View {
+ private final Drawable mDrawable;
+
+ public PatchView(Context context) {
+ super(context);
+ setBackgroundColor(0xff000000);
+ mDrawable = context.getResources().getDrawable(R.drawable.expander_ic_minimized);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.save();
+ canvas.translate(200, 200);
+ mDrawable.setBounds(3, 0, 33, 64);
+ mDrawable.draw(canvas);
+ mDrawable.setBounds(63, 0, 94, 64);
+ mDrawable.draw(canvas);
+ canvas.restore();
+ }
+ }
+}